/*
 * @(#)DmsDocument.java
 *
 * Copyright (c) 2003 DCIVision Ltd
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of DCIVision
 * Ltd ("Confidential Information").  You shall not disclose such Confidential
 * Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with DCIVision Ltd.
 */
package com.dcivision.dms.dao;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.Vector;

import org.apache.commons.dbutils.DbUtils;

import com.dcivision.alert.bean.UpdateAlert;
import com.dcivision.dms.DmsErrorConstant;
import com.dcivision.dms.DmsOperationConstant;
import com.dcivision.dms.bean.DmsDefaultProfileSetting;
import com.dcivision.dms.bean.DmsDocument;
import com.dcivision.dms.bean.DmsDocumentDetail;
import com.dcivision.dms.bean.DmsRelationalWord;
import com.dcivision.dms.bean.DmsRoot;
import com.dcivision.dms.bean.DmsVersion;
import com.dcivision.dms.core.DocumentRetrievalManager;
import com.dcivision.dms.core.DocumentValidateManager;
import com.dcivision.dms.web.ListDmsCompoundDocumentForm;
import com.dcivision.dms.web.ListDmsDocumentForm;
import com.dcivision.dms.web.ListDmsEmptyDocumentForm;
import com.dcivision.dms.web.ListDmsFolderSelectForm;
import com.dcivision.dms.web.ListDmsPaperDocumentForm;
import com.dcivision.dms.web.ListDmsSelectSingleForm;
import com.dcivision.framework.ApplicationException;
import com.dcivision.framework.DataSourceFactory;
import com.dcivision.framework.ErrorConstant;
import com.dcivision.framework.GlobalConstant;
import com.dcivision.framework.IndexManager;
import com.dcivision.framework.PermissionManager;
import com.dcivision.framework.SessionContainer;
import com.dcivision.framework.SystemParameterConstant;
import com.dcivision.framework.SystemParameterFactory;
import com.dcivision.framework.TextUtility;
import com.dcivision.framework.UserInfoFactory;
import com.dcivision.framework.Utility;
import com.dcivision.framework.bean.AbstractBaseObject;
import com.dcivision.framework.bean.SysUserDefinedIndexDetail;
import com.dcivision.framework.dao.AbstractDAObject;
import com.dcivision.framework.web.AbstractSearchForm;

/**
 DmsDocumentDAObject.java
 This class is the data access bean for table "DMS_DOCUMENT".
 @author      Zoe Shum
 @company     DCIVision Limited
 @creation date   05/08/2003
 @version     $Revision: 1.273.2.11 $
 */
/* ********************************Modify History***********************************************
 * Modify by  : Jicle.Wang 
 * Modify date: 2006/08/10
 * BugID      : 5816
 * Description: The file's postfix in Email Archive is the same as file was checked in.
 * *********************************************************************************************
 */
public class DmsDocumentDAObject extends AbstractDAObject {
  
  public static final String REVISION = "$Revision: 1.273.2.11 $";
  
  public static final String TABLE_NAME = "DMS_DOCUMENT";
  
  
  /**
   * Constructor
   * 
   * @param sessionContainer The session container object
   * @param dbConn The valid database connection
   */  
  public DmsDocumentDAObject(SessionContainer sessionContainer,
      Connection dbConn) {
    super(sessionContainer, dbConn);
  }
  
  protected void initDBSetting() {
    this.baseTableName = TABLE_NAME;
    this.vecDBColumn.add("ID");
    this.vecDBColumn.add("DOCUMENT_NAME");
    this.vecDBColumn.add("DOCUMENT_TYPE");
    this.vecDBColumn.add("PARENT_ID");
    this.vecDBColumn.add("ROOT_ID");
    this.vecDBColumn.add("CREATE_TYPE");
    this.vecDBColumn.add("EFFECTIVE_START_DATE");
    this.vecDBColumn.add("EFFECTIVE_END_DATE");
    this.vecDBColumn.add("REMINDER_AMOUNT");
    this.vecDBColumn.add("REMINDER_TYPE");
    this.vecDBColumn.add("NOTIFICATION_WAY");
    this.vecDBColumn.add("OWNER_ID");
    this.vecDBColumn.add("REFERENCE_NO");
    this.vecDBColumn.add("DESCRIPTION");
    this.vecDBColumn.add("ITEM_SIZE");
    this.vecDBColumn.add("ITEM_STATUS");
    this.vecDBColumn.add("CHECKOUT_ID");
    this.vecDBColumn.add("ALERT_EDIT_ID");
    this.vecDBColumn.add("ALERT_INVITE_ID");
    this.vecDBColumn.add("EXT_REF");
    this.vecDBColumn.add("USER_DEF_1");
    this.vecDBColumn.add("USER_DEF_2");
    this.vecDBColumn.add("USER_DEF_3");
    this.vecDBColumn.add("USER_DEF_4");
    this.vecDBColumn.add("USER_DEF_5");
    this.vecDBColumn.add("USER_DEF_6");
    this.vecDBColumn.add("USER_DEF_7");
    this.vecDBColumn.add("USER_DEF_8");
    this.vecDBColumn.add("USER_DEF_9");
    this.vecDBColumn.add("USER_DEF_10");
    this.vecDBColumn.add("RECORD_STATUS");
    this.vecDBColumn.add("UPDATE_COUNT");
    this.vecDBColumn.add("CREATOR_ID");
    this.vecDBColumn.add("CREATE_DATE");
    this.vecDBColumn.add("UPDATER_ID");
    this.vecDBColumn.add("UPDATE_DATE");
  }
  
  protected synchronized AbstractBaseObject getByID(Integer id) throws ApplicationException {
    return getByID(id, null);
  }
  
  protected synchronized AbstractBaseObject getByID(Integer id, String recordStatus) throws
  ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE, A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF,A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        //sqlStat.append("WHERE  A.ID = ? AND A.RECORD_STATUS = ? ");
        sqlStat.append("WHERE  A.ID = ?  ");
        if (!Utility.isEmpty(recordStatus)) {
          sqlStat.append("AND RECORD_STATUS=?  ");
        }
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, id);
        if (!Utility.isEmpty(recordStatus)) {
          this.setPrepareStatement(preStat, 2, recordStatus);
        }
        rs = preStat.executeQuery();
        if (rs.next()) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          return (tmpDmsDocument);
        } else {
          return null;
          //throw new ApplicationException(ErrorConstant.DB_RECORD_NOT_FOUND_ERROR);
        }
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  /**
   * Gets the DmsDocument object by the given dmsDocument object ID
   * 
   * @param id the dmsDocument object ID
   * @param recordStatus the record status of the dmsDocument
   * @return the matched DmsDocument object, null will be returned if no match object found
   * @throws ApplicationException
   * <pre>
   * 
   *            ApplicationException with the following message codes will be thrown
   *            ErrorConstant.ErrorConstant.DB_GENERAL_ERROR - General caught SQLException
   *            ErrorConstant.DB_SELECT_ERROR - All kind of caught Exception
   *  
   * </pre>
   * @see com.dcivision.dms.bean.DmsDocument
   * 
   */
  public synchronized AbstractBaseObject getDocumentByID(Integer id, String recordStatus) throws
  ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE, A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF,A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        //sqlStat.append("WHERE  A.ID = ? AND A.RECORD_STATUS = ? ");
        sqlStat.append("WHERE  A.ID = ?  ");
        if (!Utility.isEmpty(recordStatus)) {
          sqlStat.append("AND RECORD_STATUS=?  ");
        }
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, id);
        if (!Utility.isEmpty(recordStatus)) {
          this.setPrepareStatement(preStat, 2, recordStatus);
        }
        rs = preStat.executeQuery();
        if (rs.next()) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          return (tmpDmsDocument);
        } else {
          return null;
        }
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  /**
   * Gets the active and inactive DmsDocument object by the givenDmsDocument object ID 
   * 
   * @param id the document object ID
   * @return the DmsDocument object
   * @throws ApplicationException
   * 
   * <pre>
   * 
   *            ApplicationException with the following message codes will be thrown
   *            ErrorConstant.DB_RECORD_NOT_FOUND_ERROR - No matching record found
   *            ErrorConstant.ErrorConstant.DB_GENERAL_ERROR - General caught SQLException
   *            ErrorConstant.DB_SELECT_ERROR - All kind of caught Exception
   *  
   * </pre>
   * @see com.dcivision.dms.bean.DmsDocument
   */
  public synchronized AbstractBaseObject getActiveInactiveByID(Integer id) throws
  ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE, A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF, A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        //sqlStat.append("WHERE  A.ID = ? AND A.RECORD_STATUS = ? ");
        sqlStat.append("WHERE  A.ID = ?  ");
        
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, id);
        
        rs = preStat.executeQuery();
        if (rs.next()) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          return (tmpDmsDocument);
        } else {
          throw new ApplicationException(ErrorConstant.DB_RECORD_NOT_FOUND_ERROR);
        }
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  
  protected synchronized List getList(AbstractSearchForm searchForm) throws
  ApplicationException {
    PreparedStatement preStat = null;
    PreparedStatement preStatCnt = null;
    ResultSet rs = null;
    ResultSet rsCnt = null;
    StringBuffer sqlStat = new StringBuffer();
    StringBuffer sqlStatCnt = new StringBuffer();
    List result = new ArrayList();
    int totalNumOfRecord = 0;
    int rowLoopCnt = 0;
    int startOffset = TextUtility.parseInteger(searchForm.getCurStartRowNo());
    int pageSize = TextUtility.parseInteger(searchForm.getPageOffset());
    ListDmsDocumentForm docSearchForm = (ListDmsDocumentForm) searchForm;
    Timestamp currTime = Utility.getCurrentTimestamp();
    Timestamp oneDayBeforeCurrTime = Utility.addDay(currTime, -1);
    int fieldNo = 6; //at least six field is need for the prepare statement
    int countDisplayOperation=0;
    
    if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
      fieldNo =8;
    }else{
      fieldNo = 5;
    }
    
    DocumentRetrievalManager documentRetrievalManager = new DocumentRetrievalManager(sessionContainer, dbConn);
    
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT DISTINCT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE,A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF,A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        if (!Utility.isEmpty(docSearchForm.getUserDefinedFieldID())) {
          sqlStat.append(" ,DMS_DOCUMENT_INDEX DI ");
        }
        sqlStat.append("WHERE  A.RECORD_STATUS = ? AND A.ROOT_ID = ? AND A.PARENT_ID = ? ");
        
        sqlStat.append(" AND ((A.EFFECTIVE_START_DATE IS NULL OR A.EFFECTIVE_START_DATE <= ?) OR A.OWNER_ID = ?) ");
        
        if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
          sqlStat.append("       AND (((A.EFFECTIVE_START_DATE IS NULL OR A.EFFECTIVE_START_DATE <= ?) ");
          sqlStat.append("       AND (A.EFFECTIVE_END_DATE IS NULL OR A.EFFECTIVE_END_DATE > ?)) ");
          sqlStat.append("       OR A.OWNER_ID = ?) ");
        }
        
        log.debug("docSearchForm.getDisplayOption():" + docSearchForm.getDisplayOption());
        if(!Utility.isEmpty(docSearchForm.getDisplayOption())){
          if(docSearchForm.getDisplayOption().indexOf(DmsDocument.DOCUMENT_TYPE)>=0){
            sqlStat.append(" AND (A.DOCUMENT_TYPE = '" + DmsDocument.DOCUMENT_TYPE + "' ");
            countDisplayOperation++;
          }
          if(docSearchForm.getDisplayOption().indexOf(DmsDocument.FOLDER_TYPE)>=0){
            if(countDisplayOperation>0){
              sqlStat.append(" OR A.DOCUMENT_TYPE = '" + DmsDocument.FOLDER_TYPE + "' ");
            }else{
              sqlStat.append(" AND (A.DOCUMENT_TYPE = '" + DmsDocument.FOLDER_TYPE + "' ");
            }
            countDisplayOperation++;
          }
          if(docSearchForm.getDisplayOption().indexOf(DmsDocument.DOCUMENT_LINK)>=0){
            if(countDisplayOperation>0){
              sqlStat.append(" OR A.DOCUMENT_TYPE = '" + DmsDocument.DOCUMENT_LINK + "' ");
            }else{
              sqlStat.append(" AND (A.DOCUMENT_TYPE = '" + DmsDocument.DOCUMENT_LINK + "' ");
            }
            countDisplayOperation++;
          }
          if(docSearchForm.getDisplayOption().indexOf(DmsDocument.COMPOUND_DOC_TYPE)>=0){
            if(countDisplayOperation>0){
              sqlStat.append(" OR A.DOCUMENT_TYPE = '" + DmsDocument.COMPOUND_DOC_TYPE + "' ");
            }else{
              sqlStat.append(" AND (A.DOCUMENT_TYPE = '" + DmsDocument.COMPOUND_DOC_TYPE + "' ");
            }
            countDisplayOperation++;
          }
          if(docSearchForm.getDisplayOption().indexOf(DmsDocument.PAPER_DOC_TYPE)>=0){
            if(countDisplayOperation>0){
              sqlStat.append(" OR A.DOCUMENT_TYPE = '" + DmsDocument.PAPER_DOC_TYPE + "' ");
            }else{
              sqlStat.append(" AND (A.DOCUMENT_TYPE = '" + DmsDocument.PAPER_DOC_TYPE + "' ");
            }
            countDisplayOperation++;
          }
          if(docSearchForm.getDisplayOption().indexOf(DmsDocument.EMAIL_DOC_TYPE)>=0){
            if(countDisplayOperation>0){
              sqlStat.append(" OR A.DOCUMENT_TYPE = '" + DmsDocument.EMAIL_DOC_TYPE + "' ");
            }else{
              sqlStat.append(" AND (A.DOCUMENT_TYPE = '" + DmsDocument.EMAIL_DOC_TYPE + "' ");
            }
            countDisplayOperation++;
          }
          if(docSearchForm.getDisplayOption().indexOf(DmsDocument.FORM_DOC_TYPE)>=0){
            if(countDisplayOperation>0){
              sqlStat.append(" OR A.DOCUMENT_TYPE = '" + DmsDocument.FORM_DOC_TYPE + "' ");
            }else{
              sqlStat.append(" AND (A.DOCUMENT_TYPE = '" + DmsDocument.FORM_DOC_TYPE + "' ");
            }
            countDisplayOperation++;
          }
          if(docSearchForm.getDisplayOption().indexOf(DmsDocument.FLOW_DOC_TYPE)>=0){
            if(countDisplayOperation>0){
              sqlStat.append(" OR A.DOCUMENT_TYPE = '" + DmsDocument.FLOW_DOC_TYPE + "' ");
            }else{
              sqlStat.append(" AND (A.DOCUMENT_TYPE = '" + DmsDocument.FLOW_DOC_TYPE + "' ");
            }
            countDisplayOperation++;
          }
          if(docSearchForm.getDisplayOption().indexOf(DmsDocument.ORIGINSLITY_EMAIL_TYPE)>=0){
            if(countDisplayOperation>0){
              sqlStat.append(" OR A.DOCUMENT_TYPE = '" + DmsDocument.ORIGINSLITY_EMAIL_TYPE + "' ");
            }else{
              sqlStat.append(" AND (A.DOCUMENT_TYPE = '" + DmsDocument.ORIGINSLITY_EMAIL_TYPE + "' ");
            }
            countDisplayOperation++;
          }
          sqlStat.append(" ) ");
        }
        
        // Form the WHERE clause for filtering.
        /*if (searchForm.isSearchable()) {
         String searchField = searchForm.getBasicSearchField();
         if (searchField.indexOf(".") < 0) {
         searchField = "A." + searchField;
         }
         sqlStat.append("AND  " + searchField + " " +
         searchForm.getBasicSearchType() + " ? ");
         fieldNo++;
         }*/
        if (searchForm.isSearchable()) {
          String searchField = getSearchColumn(searchForm.getBasicSearchField());
          sqlStat.append("AND  " + searchField + " " + searchForm.getBasicSearchType() + " ? ");
          fieldNo++;
        }
        
        if (!Utility.isEmpty(docSearchForm.getUserDefinedFieldID())) {
          sqlStat.append("      AND A.ID=DI.DOCUMENT_ID AND DI.USER_DEFINED_FIELD_ID = ? ");
          
        }
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        // Form the ORDER clause for sorting.
        sqlStat.append("ORDER BY A.DOCUMENT_TYPE DESC  ");
        if (searchForm.isSortable()) {
          String sortAttribute = searchForm.getSortAttribute();
          if (sortAttribute.indexOf(".") < 0) {
            sortAttribute = "A." + sortAttribute;
          }
          sqlStat.append(", " + sortAttribute + " " + searchForm.getSortOrder());
          
        }
        // Get total number of record return.
        sqlStatCnt = this.getSelectCountSQL(sqlStat);
        preStatCnt = dbConn.prepareStatement(sqlStatCnt.toString());
        this.setPrepareStatement(preStatCnt, 1, GlobalConstant.RECORD_STATUS_ACTIVE);
        this.setPrepareStatement(preStatCnt, 2, docSearchForm.getRootID());
        this.setPrepareStatement(preStatCnt, 3, docSearchForm.getParentID());
        
        this.setPrepareStatement(preStatCnt, 4, currTime);
        this.setPrepareStatement(preStatCnt, 5, this.sessionContainer.getUserRecordID());
        
        
        if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
          this.setPrepareStatement(preStatCnt, 6, currTime);
          this.setPrepareStatement(preStatCnt, 7, oneDayBeforeCurrTime);
          this.setPrepareStatement(preStatCnt, 8, this.sessionContainer.getUserRecordID());
        }
        
        if (searchForm.isSearchable()) {
          
          String searchKeyword = this.getFormattedKeyword(searchForm.getBasicSearchKeyword() , searchForm.getBasicSearchType());
          if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
            this.setPrepareStatement(preStatCnt, 9, searchKeyword);
          }else{
            this.setPrepareStatement(preStatCnt, 6, searchKeyword);
          }
        }
        
        if (!Utility.isEmpty(docSearchForm.getUserDefinedFieldID())) {
          
          this.setPrepareStatement(preStatCnt, fieldNo + 1, TextUtility.parseIntegerObj(docSearchForm.getUserDefinedFieldID()));
        }
        
        rsCnt = preStatCnt.executeQuery();
        if (rsCnt.next()) {
          totalNumOfRecord = rsCnt.getInt(1);
        }
        try {
          rsCnt.close();
        } catch (Exception ignore) {} finally {
          rsCnt = null;
        }
        try {
          preStatCnt.close();
        } catch (Exception ignore) {} finally {
          preStatCnt = null;
        }
        
        // Retrieve the result in row basis.
        sqlStat = this.getSelectListSQL(sqlStat, startOffset, pageSize);
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, GlobalConstant.RECORD_STATUS_ACTIVE);
        this.setPrepareStatement(preStat, 2, docSearchForm.getRootID());
        this.setPrepareStatement(preStat, 3, docSearchForm.getParentID());
        this.setPrepareStatement(preStat, 4, currTime);
        this.setPrepareStatement(preStat, 5, this.sessionContainer.getUserRecordID());
        if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
          this.setPrepareStatement(preStat, 6, currTime);
          this.setPrepareStatement(preStat, 7, oneDayBeforeCurrTime);
          this.setPrepareStatement(preStat, 8, this.sessionContainer.getUserRecordID());
        }
        
        if (searchForm.isSearchable()) {
          String searchKeyword = this.getFormattedKeyword(searchForm.getBasicSearchKeyword(), searchForm.getBasicSearchType());
          if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
            this.setPrepareStatement(preStat, 9, searchKeyword);
          }else{
            this.setPrepareStatement(preStat, 6, searchKeyword);
          }
        }
        if (!Utility.isEmpty(docSearchForm.getUserDefinedFieldID())) {
          
          this.setPrepareStatement(preStat, fieldNo + 1, TextUtility.parseIntegerObj(docSearchForm.getUserDefinedFieldID()));
        }
        rs = preStat.executeQuery();
        this.positionCursor(rs, startOffset, pageSize);
        while (rs.next() && rowLoopCnt < pageSize) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          tmpDmsDocument.setRecordCount(totalNumOfRecord);
          tmpDmsDocument.setRowNum(startOffset++);
          tmpDmsDocument.setHasRelationship(documentRetrievalManager.hasRelationship(tmpDmsDocument.getID(), ""));
          ++rowLoopCnt;
          result.add(tmpDmsDocument);
        }
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
        try {
          rsCnt.close();
        } catch (Exception ignore) {} finally {
          rsCnt = null;
        }
        try {
          preStatCnt.close();
        } catch (Exception ignore) {} finally {
          preStatCnt = null;
        }
      }
    }
  }
  
  protected synchronized List getList() throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    List result = new ArrayList();
    Timestamp currTime = Utility.getCurrentTimestamp();
    Timestamp oneDayBeforeCurrTime = Utility.addDay(currTime, -1);
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE, A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF,A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        sqlStat.append("WHERE  A.RECORD_STATUS = ? ");
        sqlStat.append("       AND (((A.EFFECTIVE_START_DATE IS NULL OR A.EFFECTIVE_START_DATE <= ?) ");
        sqlStat.append("       AND (A.EFFECTIVE_END_DATE IS NULL OR A.EFFECTIVE_END_DATE > ?)) ");
        sqlStat.append("       OR A.OWNER_ID = ?) ");
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, GlobalConstant.RECORD_STATUS_ACTIVE);
        this.setPrepareStatement(preStat, 2, currTime);
        this.setPrepareStatement(preStat, 3, oneDayBeforeCurrTime);
        this.setPrepareStatement(preStat, 4, this.sessionContainer.getUserRecordID());
        
        rs = preStat.executeQuery();
        while (rs.next()) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          result.add(tmpDmsDocument);
        }
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  protected void validateInsert(AbstractBaseObject obj) throws ApplicationException {
    
    DmsDocument curDocument = (DmsDocument) obj;
    //Check duplicate reference number
    if(DmsDocument.PAPER_DOC_TYPE.equals(curDocument.getDocumentType())){
      
      if (!Utility.isEmpty(curDocument.getReferenceNo())) {
        DmsDocument existsDocument = (DmsDocument)this.getObjectByReferenceNo(curDocument.getReferenceNo());
        if (existsDocument != null) {
          throw new ApplicationException(DmsErrorConstant.DUPLICATE_REFERENCE_NO, null, curDocument.getReferenceNo());
        }
      }
    }
    
    //Record status is pending, check the exist of reference no.
    //DmsDocument curDocument = (DmsDocument) obj;
    
    if (DmsOperationConstant.DMS_RECORD_EMPTY.equals(curDocument.getRecordStatus()) && Utility.isEmpty(curDocument.getReferenceNo())) {
      throw new ApplicationException(DmsErrorConstant.EMPTY_REFERENCE_NO, null);
    }
    
    // check duplicate name of same level if config file defined
    DocumentValidateManager docValidateManager = new DocumentValidateManager(sessionContainer, dbConn);
    docValidateManager.checkDuplicateNameSupport(curDocument);
    log.debug(".................................No duplicate name exists");
    
  }
  
  protected void validateUpdate(AbstractBaseObject obj) throws ApplicationException {
    
    
  }
  
  protected void validateDelete(AbstractBaseObject obj) throws ApplicationException {
  }
  
  protected synchronized AbstractBaseObject insert(AbstractBaseObject obj) throws
  ApplicationException {
    PreparedStatement preStat = null;
    StringBuffer sqlStat = new StringBuffer();
    DmsDocument tmpDmsDocument = (DmsDocument) ( (DmsDocument) obj).clone();
    
    synchronized (dbConn) {
      try {
        Integer nextID = getNextPrimaryID();
        Timestamp currTime = Utility.getCurrentTimestamp();
        sqlStat.append("INSERT ");
        sqlStat.append("INTO   DMS_DOCUMENT(ID, DOCUMENT_NAME, DOCUMENT_TYPE, PARENT_ID, ROOT_ID, PRIORITY, CREATE_TYPE, EFFECTIVE_START_DATE, EFFECTIVE_END_DATE, REMINDER_AMOUNT, REMINDER_TYPE, NOTIFICATION_WAY, OWNER_ID, REFERENCE_NO, DESCRIPTION, ITEM_SIZE, ITEM_STATUS, EXT_REF , USER_DEF_1, USER_DEF_2, USER_DEF_3, USER_DEF_4, USER_DEF_5, USER_DEF_6, USER_DEF_7, USER_DEF_8, USER_DEF_9, USER_DEF_10, RECORD_STATUS, UPDATE_COUNT, CREATOR_ID, CREATE_DATE, UPDATER_ID, UPDATE_DATE) ");
        sqlStat.append("VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?) ");
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        setPrepareStatement(preStat, 1, nextID);
        if (!Utility.isEmpty(tmpDmsDocument.getDocumentName())) {
          tmpDmsDocument.setDocumentName(tmpDmsDocument.getDocumentName().trim());
        }
        setPrepareStatement(preStat, 2, tmpDmsDocument.getDocumentName());
        setPrepareStatement(preStat, 3, tmpDmsDocument.getDocumentType());
        setPrepareStatement(preStat, 4, tmpDmsDocument.getParentID());
        setPrepareStatement(preStat, 5, tmpDmsDocument.getRootID());
        setPrepareStatement(preStat, 6, tmpDmsDocument.getPriority());
        setPrepareStatement(preStat, 7, tmpDmsDocument.getCreateType());
        if (tmpDmsDocument.getEffectiveStartDate() == null) {
          tmpDmsDocument.setEffectiveStartDate(currTime);
        }
        setPrepareStatement(preStat, 8, tmpDmsDocument.getEffectiveStartDate());
        setPrepareStatement(preStat, 9, tmpDmsDocument.getEffectiveEndDate());
        setPrepareStatement(preStat, 10, tmpDmsDocument.getReminderAmount());
        setPrepareStatement(preStat, 11, tmpDmsDocument.getReminderType());
        String notificationWay = "";
        if (tmpDmsDocument.getNotificationWay() != null) {
          for (int o = 0; o < tmpDmsDocument.getNotificationWay().length; o++) {
            notificationWay = notificationWay + tmpDmsDocument.getNotificationWay()[o].toString() + ";";
          }
        }
        setPrepareStatement(preStat, 12, notificationWay);
        if (tmpDmsDocument.getOwnerID() == null) {
          tmpDmsDocument.setOwnerID(sessionContainer.getUserRecordID());
        }
        setPrepareStatement(preStat, 13, tmpDmsDocument.getOwnerID());
        setPrepareStatement(preStat, 14, tmpDmsDocument.getReferenceNo());
        setPrepareStatement(preStat, 15, tmpDmsDocument.getDescription());
        setPrepareStatement(preStat, 16, tmpDmsDocument.getItemSize());
        setPrepareStatement(preStat, 17, tmpDmsDocument.getItemStatus());
        setPrepareStatement(preStat, 18, tmpDmsDocument.getExtRef());
        setPrepareStatement(preStat, 19, tmpDmsDocument.getUserDef1());
        setPrepareStatement(preStat, 20, tmpDmsDocument.getUserDef2());
        setPrepareStatement(preStat, 21, tmpDmsDocument.getUserDef3());
        setPrepareStatement(preStat, 22, tmpDmsDocument.getUserDef4());
        setPrepareStatement(preStat, 23, tmpDmsDocument.getUserDef5());
        setPrepareStatement(preStat, 24, tmpDmsDocument.getUserDef6());
        setPrepareStatement(preStat, 25, tmpDmsDocument.getUserDef7());
        setPrepareStatement(preStat, 26, tmpDmsDocument.getUserDef8());
        setPrepareStatement(preStat, 27, tmpDmsDocument.getUserDef9());
        setPrepareStatement(preStat, 28, tmpDmsDocument.getUserDef10());
        setPrepareStatement(preStat, 29, tmpDmsDocument.getRecordStatus());
        setPrepareStatement(preStat, 30, new Integer(0));
        setPrepareStatement(preStat, 31, sessionContainer.getUserRecordID());
        setPrepareStatement(preStat, 32, currTime);
        setPrepareStatement(preStat, 33, sessionContainer.getUserRecordID());
        setPrepareStatement(preStat, 34, currTime);
        preStat.executeUpdate();
        tmpDmsDocument.setID(nextID);
        tmpDmsDocument.setCreatorID(sessionContainer.getUserRecordID());
        tmpDmsDocument.setCreateDate(currTime);
        tmpDmsDocument.setUpdaterID(sessionContainer.getUserRecordID());
        tmpDmsDocument.setUpdateDate(currTime);
        tmpDmsDocument.setUpdateCount(new Integer(0));
        tmpDmsDocument.setCreatorName(UserInfoFactory.getUserFullName(tmpDmsDocument.getCreatorID()));
        tmpDmsDocument.setUpdaterName(UserInfoFactory.getUserFullName(tmpDmsDocument.getUpdaterID()));
        return (tmpDmsDocument);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_INSERT_ERROR, e);
      } finally {
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  protected synchronized AbstractBaseObject update(AbstractBaseObject obj) throws
  ApplicationException {
    PreparedStatement preStat = null;
    StringBuffer sqlStat = new StringBuffer();
    DmsDocument tmpDmsDocument = (DmsDocument) ( (DmsDocument) obj).clone();
    if (!Utility.isEmpty(tmpDmsDocument.getReminderType()) && tmpDmsDocument.getReminderType().indexOf(";") > 0) {
      String[] reminder = TextUtility.splitString(tmpDmsDocument.getReminderType(), ";");
      //for(int i=0;i<reminder.length;i++){
      tmpDmsDocument.setReminderAmount(TextUtility.parseIntegerObj(reminder[0]));
      tmpDmsDocument.setReminderType(reminder[1]);
      //}
    }
    
    synchronized (dbConn) {
      try {
        int updateCnt = 0;
        Timestamp currTime = Utility.getCurrentTimestamp();
        sqlStat.append("UPDATE DMS_DOCUMENT ");
        sqlStat.append("SET    DOCUMENT_NAME=?, DOCUMENT_TYPE=?, PARENT_ID=?, ROOT_ID=?, PRIORITY=?, CREATE_TYPE=?, EFFECTIVE_START_DATE=?, EFFECTIVE_END_DATE=?, REMINDER_AMOUNT=?, REMINDER_TYPE=?, NOTIFICATION_WAY=?, OWNER_ID=?, REFERENCE_NO=?, DESCRIPTION=?, ITEM_SIZE=?, ITEM_STATUS=?, USER_DEF_1=?, USER_DEF_2=?, USER_DEF_3=?, USER_DEF_4=?, USER_DEF_5=?, USER_DEF_6=?, USER_DEF_7=?, USER_DEF_8=?, USER_DEF_9=?, USER_DEF_10=?, CHECKOUT_ID=?, ");
        sqlStat.append("       RECORD_STATUS=?, UPDATE_COUNT=?, UPDATER_ID=?, UPDATE_DATE=? ");
        sqlStat.append("WHERE  ID=? AND UPDATE_COUNT=? ");
        
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        
        if (!Utility.isEmpty(tmpDmsDocument.getDocumentName())) {
          tmpDmsDocument.setDocumentName(tmpDmsDocument.getDocumentName().trim());
        }
        setPrepareStatement(preStat, 1, tmpDmsDocument.getDocumentName());
        setPrepareStatement(preStat, 2, tmpDmsDocument.getDocumentType());
        setPrepareStatement(preStat, 3, tmpDmsDocument.getParentID());
        setPrepareStatement(preStat, 4, tmpDmsDocument.getRootID());
        setPrepareStatement(preStat, 5, tmpDmsDocument.getPriority());
        setPrepareStatement(preStat, 6, tmpDmsDocument.getCreateType());
        if (tmpDmsDocument.getEffectiveStartDate() != null) {
          setPrepareStatement(preStat, 7, tmpDmsDocument.getEffectiveStartDate());
        } else {
          setPrepareStatement(preStat, 7, currTime);
        }
        
        setPrepareStatement(preStat, 8, tmpDmsDocument.getEffectiveEndDate());
        setPrepareStatement(preStat, 9, tmpDmsDocument.getReminderAmount());
        setPrepareStatement(preStat, 10, tmpDmsDocument.getReminderType());
        String notificationWay = "";
        if (tmpDmsDocument.getNotificationWay() != null) {
          for (int o = 0; o < tmpDmsDocument.getNotificationWay().length; o++) {
            notificationWay = notificationWay + tmpDmsDocument.getNotificationWay()[o].toString() + ";";
          }
        }
        setPrepareStatement(preStat, 11, notificationWay);
        setPrepareStatement(preStat, 12, tmpDmsDocument.getOwnerID());
        setPrepareStatement(preStat, 13, tmpDmsDocument.getReferenceNo());
        setPrepareStatement(preStat, 14, tmpDmsDocument.getDescription());
        setPrepareStatement(preStat, 15, tmpDmsDocument.getItemSize());
        setPrepareStatement(preStat, 16, tmpDmsDocument.getItemStatus());
        setPrepareStatement(preStat, 17, tmpDmsDocument.getUserDef1());
        setPrepareStatement(preStat, 18, tmpDmsDocument.getUserDef2());
        setPrepareStatement(preStat, 19, tmpDmsDocument.getUserDef3());
        setPrepareStatement(preStat, 20, tmpDmsDocument.getUserDef4());
        setPrepareStatement(preStat, 21, tmpDmsDocument.getUserDef5());
        setPrepareStatement(preStat, 22, tmpDmsDocument.getUserDef6());
        setPrepareStatement(preStat, 23, tmpDmsDocument.getUserDef7());
        setPrepareStatement(preStat, 24, tmpDmsDocument.getUserDef8());
        setPrepareStatement(preStat, 25, tmpDmsDocument.getUserDef9());
        setPrepareStatement(preStat, 26, tmpDmsDocument.getUserDef10());
        setPrepareStatement(preStat, 27, tmpDmsDocument.getCheckoutID());
        setPrepareStatement(preStat, 28, tmpDmsDocument.getRecordStatus());
        setPrepareStatement(preStat, 29, new Integer(tmpDmsDocument.getUpdateCount().intValue() + 1));
        setPrepareStatement(preStat, 30, sessionContainer.getUserRecordID());
        setPrepareStatement(preStat, 31, currTime);
        setPrepareStatement(preStat, 32, tmpDmsDocument.getID());
        setPrepareStatement(preStat, 33, tmpDmsDocument.getUpdateCount());
        updateCnt = preStat.executeUpdate();
        if (updateCnt == 0) {
          throw new ApplicationException(ErrorConstant.DB_CONCURRENT_ERROR);
        } else {
          tmpDmsDocument.setUpdaterID(sessionContainer.getUserRecordID());
          tmpDmsDocument.setUpdateDate(currTime);
          tmpDmsDocument.setUpdateCount(new Integer(tmpDmsDocument.getUpdateCount().intValue() + 1));
          tmpDmsDocument.setCreatorName(UserInfoFactory.getUserFullName(tmpDmsDocument.getCreatorID()));
          tmpDmsDocument.setUpdaterName(UserInfoFactory.getUserFullName(tmpDmsDocument.getUpdaterID()));
          return (tmpDmsDocument);
        }
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_UPDATE_ERROR, e);
      } finally {
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  protected synchronized AbstractBaseObject delete(AbstractBaseObject obj) throws
  ApplicationException {
    PreparedStatement preStat = null;
    StringBuffer sqlStat = new StringBuffer();
    DmsDocument tmpDmsDocument = (DmsDocument) ( (DmsDocument) obj).clone();
    
    synchronized (dbConn) {
      try {
        int updateCnt = 0;
        sqlStat.append("DELETE ");
        sqlStat.append("FROM   DMS_DOCUMENT ");
        sqlStat.append("WHERE  ID=? AND UPDATE_COUNT=? ");
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        setPrepareStatement(preStat, 1, tmpDmsDocument.getID());
        setPrepareStatement(preStat, 2, tmpDmsDocument.getUpdateCount());
        updateCnt = preStat.executeUpdate();
        if (updateCnt == 0) {
          throw new ApplicationException(ErrorConstant.DB_CONCURRENT_ERROR);
        } else {
          return (tmpDmsDocument);
        }
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_DELETE_ERROR, e);
      } finally {
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  protected synchronized void auditTrail(String opMode, AbstractBaseObject obj) throws
  ApplicationException {
    Vector oldValues = new Vector();
    Vector newValues = new Vector();
    DmsDocument tmpDmsDocument = (DmsDocument)this.oldValue;
    
    if (tmpDmsDocument != null) {
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getID()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getDocumentName()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getDocumentType()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getParentID()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getRootID()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getCreateType()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getEffectiveStartDate()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getEffectiveEndDate()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getReminderAmount()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getReminderType()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getNotificationWay()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getOwnerID()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getReferenceNo()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getDescription()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getItemSize()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getItemStatus()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getCheckoutID()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getAlertEditID()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getAlertInviteID()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getUserDef1()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getUserDef2()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getUserDef3()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getUserDef4()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getUserDef5()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getUserDef6()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getUserDef7()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getUserDef8()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getUserDef9()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getUserDef10()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getRecordStatus()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getUpdateCount()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getCreatorID()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getCreateDate()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getUpdaterID()));
      oldValues.add(toAuditTrailValue(tmpDmsDocument.getUpdateDate()));
    }
    
    tmpDmsDocument = (DmsDocument) obj;
    if (tmpDmsDocument != null) {
      newValues.add(toAuditTrailValue(tmpDmsDocument.getID()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getDocumentName()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getDocumentType()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getParentID()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getRootID()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getCreateType()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getEffectiveStartDate()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getEffectiveEndDate()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getReminderAmount()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getReminderType()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getNotificationWay()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getOwnerID()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getReferenceNo()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getDescription()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getItemSize()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getItemStatus()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getCheckoutID()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getAlertEditID()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getAlertInviteID()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getUserDef1()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getUserDef2()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getUserDef3()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getUserDef4()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getUserDef5()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getUserDef6()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getUserDef7()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getUserDef8()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getUserDef9()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getUserDef10()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getRecordStatus()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getUpdateCount()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getCreatorID()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getCreateDate()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getUpdaterID()));
      newValues.add(toAuditTrailValue(tmpDmsDocument.getUpdateDate()));
    }
    
    auditTrailBase(opMode, oldValues, newValues);
  }
  
  /***********************************************************************
   * DON'T Modify the codes above unless you know what you are doing!!!  *
   * Put your own functions beblow.                                      *
   * For FINDER methods, the function name should be in the notation:    *
   *   public Object getObjectBy<Criteria>()                             *
   *   - e.g. public Object getObjectByCode()                            *
   *   public List getListBy<Criteria>()                                 *
   *   - e.g. public List getListByUserID()                              *
   * For OPERATION methods, the function name should be in the notation: *
   *   public void <Operation>ObjectBy<Criteria>()                       *
   *   - e.g. public void deleteObjectByCode()                           *
   *   public void <Operation>ListBy<Criteria>()                         *
   *   - e.g. public void deleteListByUserID()                           *
   ***********************************************************************/
  
  /**
   * Gets the document profile information by the given DmsDocument object ID
   *
   * @param documentID  the DmsDocument object id
   * @return the list of document profile information
   * <PRE>
   * 
   * The items of the list contains:
   * First item:      A String array which store 
   *                     [Doc Name][Num of Version][Cur Version][Doc Type]
   * Following items: A String array which store  
   *                     [Profile Name][Field Name][Field Value]
   * 
   * </PRE>
   * @throws ApplicationException
   * <pre>
   * 
   *            ApplicationException with the following message codes will be thrown
   *            ErrorConstant.DB_RECORD_NOT_FOUND_ERROR - No matching record found
   *            ErrorConstant.ErrorConstant.DB_GENERAL_ERROR - General caught SQLException
   *            ErrorConstant.DB_SELECT_ERROR - All kind of caught Exception
   *  
   * </pre>
   */
  public synchronized List getDocumentProfileInfo(Integer documentID) throws ApplicationException {
    DmsDocument docObject = new DmsDocument();
    docObject.setID(documentID);
    return (this.getDocumentProfileInfo(docObject));
  }
  
  /**
   * Gets the document profile information by the given DmsDocument objec
   *
   * @param docObject the dmsDocument object 
   * @return the list of document profile information
   * <PRE>
   * 
   * The items of the list contains:
   * First item:      A String array which store 
   *                     [Doc Name][Num of Version][Cur Version][Doc Type]
   * Following items: A String array which store  
   *                     [Profile Name][Field Name][Field Value]
   * 
   * </PRE>
   * @throws ApplicationException
   * <pre>
   * 
   *            ApplicationException with the following message codes will be thrown
   *            ErrorConstant.DB_RECORD_NOT_FOUND_ERROR - No matching record found
   *            ErrorConstant.ErrorConstant.DB_GENERAL_ERROR - General caught SQLException
   *            ErrorConstant.DB_SELECT_ERROR - All kind of caught Exception
   *  
   * </pre>
   */
  public synchronized List getDocumentProfileInfo(DmsDocument docObject) throws ApplicationException {
    List result = new ArrayList();
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    
    synchronized (dbConn) {
      try {
        // Get the document name and document type.
        String documentName = "";
        String documentType = "";
        String numOfVersion = "";
        StringBuffer curVersion = new StringBuffer();
        if (Utility.isEmpty(docObject.getDocumentType())) {
          sqlStat.append("SELECT A.DOCUMENT_NAME, A.DOCUMENT_TYPE ");
          sqlStat.append("FROM   DMS_DOCUMENT A ");
          sqlStat.append("WHERE  A.ID = ? ");
          
          //format the sql for any 'LIKE' statement contained
          sqlStat = this.getFormattedSQL(sqlStat.toString());
          
          preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
          this.setPrepareStatement(preStat, 1, docObject.getID());
          
          rs = preStat.executeQuery();
          if (rs.next()) {
            documentName = rs.getString(1);
            documentType = rs.getString(2);
          } else {
            throw new ApplicationException(ErrorConstant.DB_RECORD_NOT_FOUND_ERROR);
          }
          try {
            rs.close();
          } catch (Exception ignore) {} finally {
            rs = null;
          }
          try {
            preStat.close();
          } catch (Exception ignore) {} finally {
            preStat = null;
          }
          
        } else {
          documentName = docObject.getDocumentName();
          documentType = docObject.getDocumentType();
        }
        
        // Get the no. of version.
        sqlStat = new StringBuffer();
        sqlStat.append("SELECT COUNT(*) ");
        sqlStat.append("FROM   DMS_VERSION A ");
        sqlStat.append("WHERE  A.DOCUMENT_ID = ? ");
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, docObject.getID());
        rs = preStat.executeQuery();
        if (rs.next()) {
          numOfVersion = rs.getString(1);
        }
        
        //get lastest version object
        String curVersionID = "";
        String curDocumentVersionID = "";
        sqlStat = new StringBuffer();
        sqlStat.append("SELECT MAX(A.ID) ");
        sqlStat.append("FROM   DMS_VERSION A ");
        sqlStat.append("WHERE  A.DOCUMENT_ID = ? ");
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, docObject.getID());
        rs = preStat.executeQuery();
        if (rs.next()) {
          curVersionID = rs.getString(1);
        }
        
        // Get the cur major version
        sqlStat = new StringBuffer();
        String parentID = "";
        sqlStat.append("SELECT A.VERSION_NUMBER, A.PARENT_ID ");
        sqlStat.append("FROM   DMS_VERSION A ");
        sqlStat.append("WHERE  ID = ? ");
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, curVersionID);
        rs = preStat.executeQuery();
        if (rs.next()) {
          curDocumentVersionID = rs.getString(1);
        }
        curVersion.append(curDocumentVersionID);
        
        // Add the first row. [Doc Name][Num of Version][Cur Version][Doc Type]
        result.add(new String[] {documentName, numOfVersion.toString(), curVersion.toString(), documentType});
        
        sqlStat = new StringBuffer();
        sqlStat.append("SELECT DISTINCT A.USER_DEFINED_TYPE, A.ID ");
        sqlStat.append("FROM   SYS_USER_DEFINED_INDEX A, DMS_DOCUMENT_DETAIL B ");
        sqlStat.append("WHERE  B.DOCUMENT_ID = ? AND A.ID = B.USER_DEFINED_FIELD_ID ");
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, docObject.getID());
        rs = preStat.executeQuery();
        
        PreparedStatement preStat2 = null;
        ResultSet rs2 = null;
        StringBuffer sqlStat2 = new StringBuffer();
        
        sqlStat2.append("SELECT B.FIELD_NAME, A.FIELD_VALUE, A.DATE_VALUE, A.NUMERIC_VALUE, B.FIELD_TYPE ");
        sqlStat2.append("FROM   DMS_DOCUMENT_DETAIL A, SYS_USER_DEFINED_INDEX_DETAIL B ");
        sqlStat2.append("WHERE  A.DOCUMENT_ID = ? AND B.ID = A.USER_DEFINED_FIELD_DETAIL_ID AND A.USER_DEFINED_FIELD_ID = ? ");
        sqlStat2.append("ORDER BY A.USER_DEFINED_FIELD_DETAIL_ID ASC");
        
        try {
          while (rs.next()) {
            preStat2 = dbConn.prepareStatement(sqlStat2.toString());
            this.setPrepareStatement(preStat2, 1, docObject.getID());
            this.setPrepareStatement(preStat2, 2, new Integer(rs.getInt(2)));
            rs2 = preStat2.executeQuery();
            String profileName = rs.getString(1);
            String fieldName = "";
            String fieldValue = "";
            
            while (rs2.next()) {
              // Add the follow rows. [Profile Name][Field Name][Field Value]
              fieldName = rs2.getString(1);
              String tmpStr2 = rs2.getString(2);
              Timestamp tmpStr3 = rs2.getTimestamp(3);
              String tmpStr4 = rs2.getString(4);
              String tmpStr5 = rs2.getString(5);
              
              if (SysUserDefinedIndexDetail.DATE_FIELD.equals(tmpStr5)) {
                fieldValue = TextUtility.formatTimestampToDate(tmpStr3);
              } else if (SysUserDefinedIndexDetail.NUMBER_FIELD.equals(tmpStr5)) {
                fieldValue = tmpStr4;
              } else {
                fieldValue = tmpStr2;
              }
              result.add(new String[] {profileName, fieldName, fieldValue});
            }
            if (!Utility.isEmpty(profileName) && Utility.isEmpty(fieldName)) {
              result.add(new String[] {profileName, fieldName, fieldValue});
            }
            try {
              rs2.close();
            } catch (Exception ignore) {} finally {
              rs2 = null;
            }
            try {
              preStat2.close();
            } catch (Exception ignore) {} finally {
              preStat2 = null;
            }
          }
        } catch (SQLException sqle) {
          log.error(sqle, sqle);
          throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
        } catch (Exception e) {
          log.error(e, e);
          throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
        } finally {
          try {
            rs2.close();
          } catch (Exception ignore) {} finally {
            rs2 = null;
          }
          try {
            preStat2.close();
          } catch (Exception ignore) {} finally {
            preStat2 = null;
          }
        }
        
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  /**
   * Gets the Dmsdocument object by given dmsDocument object ID
   * <P>
   * This method mainly used to get the folder document object that folder only has one version.
   * </P>
   * @param docID the DmsDocument object ID
   * @return the DmsDocument object, empty DmsDocument object if no match DmsDocument object.
   * @throws ApplicationException
   * <pre>
   * 
   *            ApplicationException with the following message codes will be thrown
   *            ErrorConstant.ErrorConstant.DB_GENERAL_ERROR - General caught SQLException
   *            ErrorConstant.DB_SELECT_ERROR - All kind of caught Exception
   *  
   * </pre>
   */
  public synchronized AbstractBaseObject getVersionDetailByDocumentID(Integer docID) throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    DmsDocument tmpDmsDocument = new DmsDocument();
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE, A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID,A.EXT_REF, A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A, DMS_VERSION V ");
        sqlStat.append("WHERE  A.ID = V.DOCUMENT_ID AND A.RECORD_STATUS = ? AND A.ID = ? ");
        sqlStat.append("ORDER BY V.VERSION_NUMBER");
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, GlobalConstant.RECORD_STATUS_ACTIVE);
        this.setPrepareStatement(preStat, 2, docID);
        rs = preStat.executeQuery();
        if (rs.next()) {
          tmpDmsDocument = parseObjectFromResultSet(rs);
        }
        return (tmpDmsDocument);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  /**
   * Gets the existing DmsDocument object with the same name of the given document under the same folder
   * 
   * @param dmsDocument the given DmsDocument object
   * @return the existing DmsDocument object with the same name, null if no same name doucment found
   * @throws ApplicationException
   * 
   * <pre>
   * 
   *            ApplicationException with the following message codes will be thrown
   *            ErrorConstant.ErrorConstant.DB_GENERAL_ERROR - General caught SQLException
   *            ErrorConstant.DB_SELECT_ERROR - All kind of caught Exception
   *  
   * </pre>
   */
  public synchronized List getDuplicateNameInSameLevel(DmsDocument dmsDocument) throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    DmsDocument tmpDmsDocument = null;
    List result = new ArrayList();
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE, A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF,A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        sqlStat.append("WHERE  (A.RECORD_STATUS = ? OR A.RECORD_STATUS = ?  OR A.RECORD_STATUS = ? ) AND ((A.PARENT_ID = ? AND A.ROOT_ID = ? AND A.PARENT_ID <> 0) OR ( A.DOCUMENT_NAME <> ? AND A.PARENT_ID = 0)) AND A.DOCUMENT_NAME = ? ");
        
        //for short cut can same name as file, but cannot duplicate file name between short cut name together
        if ( (DmsDocument.DOCUMENT_LINK).equals(dmsDocument.getDocumentType())) {
          sqlStat.append(" AND A.DOCUMENT_TYPE = ? ");
        }
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, GlobalConstant.RECORD_STATUS_ACTIVE);
        this.setPrepareStatement(preStat, 2, DmsOperationConstant.DMS_RECORD_EMPTY);
        this.setPrepareStatement(preStat, 3, GlobalConstant.RECORD_STATUS_PENDING);             
        this.setPrepareStatement(preStat, 4, dmsDocument.getParentID());
        this.setPrepareStatement(preStat, 5, dmsDocument.getRootID());
        this.setPrepareStatement(preStat, 6, DmsOperationConstant.DMS_PERSONAL_ROOT);
        this.setPrepareStatement(preStat, 7, dmsDocument.getDocumentName());
        if ( (DmsDocument.DOCUMENT_LINK).equals(dmsDocument.getDocumentType())) {
          this.setPrepareStatement(preStat, 8, DmsDocument.DOCUMENT_LINK);
        }
        
        
        rs = preStat.executeQuery();
        
        while (rs.next()) {
          result.add(parseObjectFromResultSet(rs));
        }
        return result;
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  
  /**
   * Gets the list of the DmsDocument objects under the same parent document. i.e. the list of the document with the same parent ID.
   * 
   * <P>
   * Only the Active document will be include in the result list.
   * if SystemParameterConstant.DMS_SHOW_EXPIRE_DOC is false, the expire document is not include in the result list except the current
   * user the document owner.
   * </P> 
   * 
   * @param parentID  the parent ID of the DmsDocument object
   * @param rootID  the root ID of the DmsDocument object
   * @return list of the DmsDocument objects under the same parent document
   * @throws ApplicationException
   * <pre>
   * 
   *            ApplicationException with the following message codes will be thrown
   *            ErrorConstant.ErrorConstant.DB_GENERAL_ERROR - General caught SQLException
   *            ErrorConstant.DB_SELECT_ERROR - All kind of caught Exception
   *  
   * </pre>
   * @see com.dcivision.framework.SystemParameterConstant#DMS_SHOW_EXPIRE_DOC
   */
  public synchronized List getListByParentID(Integer parentID, Integer rootID) throws ApplicationException {
    
    return (this.getListByParentID(parentID, rootID, "*"));
  }
  
  /**
   * Gets the list of the DmsDocument objects under the same parent document. i.e. the list of the document with the same parent ID.
   * 
   * <P>
   * Reference (empty) document will not include in the result list
   * Only the Active document will be include in the result list.
   * if SystemParameterConstant.DMS_SHOW_EXPIRE_DOC is false, the expire document is not include in the result list except the current 
   * user the the document owner
   * </P>
   * 
   * @param parentID  the parent ID of the DmsDocument object
   * @param rootID  the root ID of the DmsDocument object
   * @param documentType the specified object type, "*" indicate all document type, if no "*" the DmsDocument object specified document 
   *                     type and the default compound or paper document dmsDocument object will be add to the return list
   * @return list of the DmsDocument objects under the same parent document
   * @throws ApplicationException
   * <pre>
   * 
   *            ApplicationException with the following message codes will be thrown
   *            ErrorConstant.ErrorConstant.DB_GENERAL_ERROR - General caught SQLException
   *            ErrorConstant.DB_SELECT_ERROR - All kind of caught Exception
   *  
   * </pre>
   * @see com.dcivision.framework.SystemParameterConstant#DMS_SHOW_EXPIRE_DOC
   */
  public synchronized List getListByParentID(Integer parentID, Integer rootID, String documentType) throws ApplicationException {
    return (this.getListByParentID(parentID, rootID, documentType, false));
  }
  
  /**
   * Gets the list of the DmsDocument objects under the same parent document. i.e. the list of the document with the same parent ID
   * <P>
   * Only the Active document will be include in the result list.
   * if SystemParameterConstant.DMS_SHOW_EXPIRE_DOC is false, the expire document is not include in the result list except the current user
   * is the document owner
   * </P>
   * 
   * 
   * @param parentID  the parent ID of the DmsDocument object
   * @param rootID  the root ID of the DmsDocument object
   * @param documentType the specified object type, "*" indicate all document type, if no "*" the DmsDocument object specified document 
   *                     type and the default compound or paper document dmsDocument object will be add to the return list
   * @param getReferenceFile true if reference(empty) document include as result list 
   * @return list of the DmsDocument objects under the same parent document
   * @throws ApplicationException
   * <pre>
   * 
   *            ApplicationException with the following message codes will be thrown
   *            ErrorConstant.ErrorConstant.DB_GENERAL_ERROR - General caught SQLException
   *            ErrorConstant.DB_SELECT_ERROR - All kind of caught Exception
   *  
   * </pre>
   * 
   */
  public synchronized List getListByParentID(Integer parentID, Integer rootID, String documentType, boolean getReferenceFile) throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    List result = new ArrayList();
    Timestamp currTime = Utility.getCurrentTimestamp();
    Timestamp oneDayBeforeCurrTime = Utility.addDay(currTime, -1);
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE, A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF,A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        sqlStat.append("WHERE  (A.RECORD_STATUS = ? OR A.RECORD_STATUS = ? ");
        
        if(getReferenceFile){
          sqlStat.append(" OR A.RECORD_STATUS = ? " );
        }
        
        
        sqlStat.append(" ) AND A.PARENT_ID = ?   ");
        if (rootID != null) {
          sqlStat.append("AND A.ROOT_ID = ? ");
        }
        
        sqlStat.append("AND ((A.EFFECTIVE_START_DATE IS NULL OR A.EFFECTIVE_START_DATE <= ?) OR A.OWNER_ID=?)");
        if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
          sqlStat.append("       AND ((A.EFFECTIVE_END_DATE IS NULL OR A.EFFECTIVE_END_DATE > ?) ");
          sqlStat.append("       OR A.OWNER_ID = ?) ");
        }
        
        if (!"*".equals(documentType)) {
          sqlStat.append("AND (A.DOCUMENT_TYPE = ? OR A.DOCUMENT_TYPE = '" + DmsDocument.COMPOUND_DOC_TYPE + "' OR A.DOCUMENT_TYPE='"+DmsDocument.PAPER_DOC_TYPE+"' ) ");
        }
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        sqlStat.append("ORDER BY A.DOCUMENT_TYPE ASC, A.DOCUMENT_NAME ASC ");
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        int i = 0;
        this.setPrepareStatement(preStat, ++i, GlobalConstant.RECORD_STATUS_ACTIVE);
        this.setPrepareStatement(preStat, ++i, GlobalConstant.RECORD_STATUS_PENDING);
        
        if(getReferenceFile){
          this.setPrepareStatement(preStat, ++i, DmsOperationConstant.DMS_RECORD_EMPTY);
        }
        
        this.setPrepareStatement(preStat, ++i, parentID);
        if (rootID != null) {
          this.setPrepareStatement(preStat, ++i, rootID);
        }
        this.setPrepareStatement(preStat, ++i, currTime);
        this.setPrepareStatement(preStat, ++i, this.sessionContainer.getUserRecordID());
        if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
          this.setPrepareStatement(preStat, ++i, oneDayBeforeCurrTime);
          this.setPrepareStatement(preStat, ++i, this.sessionContainer.getUserRecordID());
        }
        
        if (!"*".equals(documentType)) {
          this.setPrepareStatement(preStat, ++i, documentType);
        }
        rs = preStat.executeQuery();
        while (rs.next()) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          result.add(tmpDmsDocument);
        }
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  /**
   * Gets the list of the DmsDocument objects with record status under the same parent document. i.e. the list of the document with the same parent ID
   * 
   * @param parentID  the parent ID of the DmsDocument object
   * @param rootID  the root ID of the DmsDocument object
   * @param documentType the specified object type, "*" indicate all document type, if no "*" the DmsDocument object specified document 
   *                     type and the default compound or paper document dmsDocument object will be add to the return list
   * @param recordStatus the record status of the  DmsDocument object
   * @return list of the DmsDocument objects under the same parent document
   * @throws ApplicationException
   * <pre>
   * 
   *            ApplicationException with the following message codes will be thrown
   *            ErrorConstant.ErrorConstant.DB_GENERAL_ERROR - General caught SQLException
   *            ErrorConstant.DB_SELECT_ERROR - All kind of caught Exception
   *  
   * </pre>
   * 
   */
  public synchronized List getListByParentIDRecordStatus(Integer parentID, Integer rootID, String documentType, String recordStatus) throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    List result = new ArrayList();
    Timestamp currTime = Utility.getCurrentTimestamp();
    Timestamp oneDayBeforeCurrTime = Utility.addDay(currTime, -1);
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE, A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF,A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        sqlStat.append("WHERE  A.RECORD_STATUS = ? ");
        
        sqlStat.append(" AND A.PARENT_ID = ?   ");
        if (rootID != null) {
          sqlStat.append("AND A.ROOT_ID = ? ");
        }
        
        if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
          sqlStat.append("      AND (((A.EFFECTIVE_START_DATE IS NULL OR A.EFFECTIVE_START_DATE <=?) ");
          sqlStat.append("      AND (A.EFFECTIVE_END_DATE IS NULL OR A.EFFECTIVE_END_DATE >?)) ");
          sqlStat.append("      OR A.OWNER_ID = ?) ");
        }
        
        if (!"*".equals(documentType)) {
          sqlStat.append("AND (A.DOCUMENT_TYPE = ? OR A.DOCUMENT_TYPE = '" + DmsDocument.COMPOUND_DOC_TYPE + "' OR A.DOCUMENT_TYPE='"+DmsDocument.PAPER_DOC_TYPE+"' OR A.DOCUMENT_TYPE='"+DmsDocument.FORM_DOC_TYPE+"' OR A.DOCUMENT_TYPE='"+DmsDocument.FLOW_DOC_TYPE+"') ");
        }
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        sqlStat.append("ORDER BY A.DOCUMENT_TYPE ASC, A.DOCUMENT_NAME ASC ");
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        int i = 0;
        this.setPrepareStatement(preStat, ++i, recordStatus);
        
        this.setPrepareStatement(preStat, ++i, parentID);
        if (rootID != null) {
          this.setPrepareStatement(preStat, ++i, rootID);
        }
        
        if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
          this.setPrepareStatement(preStat, ++i, currTime);
          this.setPrepareStatement(preStat, ++i, oneDayBeforeCurrTime);
          this.setPrepareStatement(preStat, ++i, this.sessionContainer.getUserRecordID());
        }
        
        if (!"*".equals(documentType)) {
          this.setPrepareStatement(preStat, ++i, documentType);
        }
        rs = preStat.executeQuery();
        while (rs.next()) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          result.add(tmpDmsDocument);
        }
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  public synchronized List getListByParentIDRecordStatus(Integer parentID, Integer rootID, String documentType, String recordStatus, String sortAttribute, String sortOrder) throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    List result = new ArrayList();
    Timestamp currTime = Utility.getCurrentTimestamp();
    Timestamp oneDayBeforeCurrTime = Utility.addDay(currTime, -1);
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE, A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF,A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        sqlStat.append("WHERE  A.RECORD_STATUS = ? ");
        
        sqlStat.append(" AND A.PARENT_ID = ?   ");
        if (rootID != null) {
          sqlStat.append("AND A.ROOT_ID = ? ");
        }
        
        if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
          sqlStat.append("      AND (((A.EFFECTIVE_START_DATE IS NULL OR A.EFFECTIVE_START_DATE <=?) ");
          sqlStat.append("      AND (A.EFFECTIVE_END_DATE IS NULL OR A.EFFECTIVE_END_DATE >?)) ");
          sqlStat.append("      OR A.OWNER_ID = ?) ");
        }
        
        if (!"*".equals(documentType)) {
          sqlStat.append("AND (A.DOCUMENT_TYPE = ? OR A.DOCUMENT_TYPE = '" + DmsDocument.COMPOUND_DOC_TYPE + "' OR A.DOCUMENT_TYPE='"+DmsDocument.PAPER_DOC_TYPE+"' OR A.DOCUMENT_TYPE='"+DmsDocument.EMAIL_DOC_TYPE+"' OR A.DOCUMENT_TYPE='"+DmsDocument.FORM_DOC_TYPE+"' OR A.DOCUMENT_TYPE='"+DmsDocument.FLOW_DOC_TYPE+"') ");
        }
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        sortAttribute = "A." + sortAttribute + " " +sortOrder;
        sqlStat.append("ORDER BY " + sortAttribute);
        //sqlStat.append("ORDER BY A.DOCUMENT_TYPE ASC, A.DOCUMENT_NAME ASC ");
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        int i = 0;
        this.setPrepareStatement(preStat, ++i, recordStatus);
        
        this.setPrepareStatement(preStat, ++i, parentID);
        if (rootID != null) {
          this.setPrepareStatement(preStat, ++i, rootID);
        }
        
        if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
          this.setPrepareStatement(preStat, ++i, currTime);
          this.setPrepareStatement(preStat, ++i, oneDayBeforeCurrTime);
          this.setPrepareStatement(preStat, ++i, this.sessionContainer.getUserRecordID());
        }
        
        if (!"*".equals(documentType)) {
          this.setPrepareStatement(preStat, ++i, documentType);
        }
        rs = preStat.executeQuery();
        while (rs.next()) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          result.add(tmpDmsDocument);
        }
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  
  
  /**
   * Gets the list of the DmsDocument objects that is marked deleted under the specified folder.
   * i.e. gets the inactive document with the same parenet ID.
   * 
   * @param parentID the DmsDocument object parent ID
   * @param rootID   the DmsDocument object root Id
   * @return list of the deleted DmsDocument object
   * @throws ApplicationException
   * 
   * <pre>
   * 
   *            ApplicationException with the following message codes will be thrown
   *            ErrorConstant.ErrorConstant.DB_GENERAL_ERROR - General caught SQLException
   *            ErrorConstant.DB_SELECT_ERROR - All kind of caught Exception
   *  
   * </pre>
   */
  public synchronized List getInactiveListByParentID(Integer parentID, Integer rootID) throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    List result = new ArrayList();
    Timestamp currTime = Utility.getCurrentTimestamp();
    Timestamp oneDayBeforeCurrTime = Utility.addDay(currTime, -1);
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE, A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF,A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        sqlStat.append("WHERE  A.RECORD_STATUS = ?  AND A.PARENT_ID = ?   ");
        if (rootID != null) {
          sqlStat.append("AND A.ROOT_ID = ? ");
        }
        sqlStat.append("      AND (((A.EFFECTIVE_START_DATE IS NULL OR A.EFFECTIVE_START_DATE <=?) ");
        sqlStat.append("      AND (A.EFFECTIVE_END_DATE IS NULL OR A.EFFECTIVE_END_DATE >?)) ");
        sqlStat.append("      OR A.OWNER_ID = ?) ");
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        sqlStat.append("ORDER BY A.DOCUMENT_TYPE ASC, A.DOCUMENT_NAME ASC ");
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        int i = 0;
        this.setPrepareStatement(preStat, ++i, GlobalConstant.RECORD_STATUS_INACTIVE);
        
        this.setPrepareStatement(preStat, ++i, parentID);
        if (rootID != null) {
          this.setPrepareStatement(preStat, ++i, rootID);
        }
        this.setPrepareStatement(preStat, ++i, currTime);
        this.setPrepareStatement(preStat, ++i, oneDayBeforeCurrTime);
        this.setPrepareStatement(preStat, ++i, this.sessionContainer.getUserRecordID());
        
        rs = preStat.executeQuery();
        while (rs.next()) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs); 
          result.add(tmpDmsDocument);
        }
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  /**
   * Gets the DmsDocument object by documen name, parent ID and the creator ID
   * @param name the document name
   * @param parentID the parent Id
   * @param creatorID the creator ID
   * @return the DmsDocument object matched, null if no matched.
   * @throws ApplicationException
   * <pre>
   * 
   *            ApplicationException with the following message codes will be thrown
   *            ErrorConstant.ErrorConstant.DB_GENERAL_ERROR - General caught SQLException
   *            ErrorConstant.DB_SELECT_ERROR - All kind of caught Exception
   *  
   * </pre>  
   * 
   */
  public synchronized DmsDocument getDocumentByNameParentIDCreatorID(String name, Integer parentID, Integer creatorID) throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    DmsDocument tmpDmsDocument = new DmsDocument();
    
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE,A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF,A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
//      sqlStat.append("WHERE  A.DOCUMENT_NAME = ? AND A.PARENT_ID = ? AND A.CREATOR_ID = ? AND A.RECORD_STATUS = ? ");
        sqlStat.append("WHERE  A.DOCUMENT_NAME = ? AND A.PARENT_ID = ? AND A.OWNER_ID = ? AND A.RECORD_STATUS = ? ");
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, name);
        this.setPrepareStatement(preStat, 2, parentID);
        this.setPrepareStatement(preStat, 3, creatorID);
        this.setPrepareStatement(preStat, 4, GlobalConstant.RECORD_STATUS_ACTIVE);
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        rs = preStat.executeQuery();
        
        if (rs.next()) {
          tmpDmsDocument = parseObjectFromResultSet(rs);
          return (tmpDmsDocument);
        } else {
          return (null);
        }
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  /**
   * Gets the document by the document name and parent D
   * 
   * @param name the document name
   * @param parentID the parent Id
   * @return the DmsDocument object matched, null if no matched.
   * @throws ApplicationException
   * <pre>
   * 
   *            ApplicationException with the following message codes will be thrown
   *            ErrorConstant.ErrorConstant.DB_GENERAL_ERROR - General caught SQLException
   *            ErrorConstant.DB_SELECT_ERROR - All kind of caught Exception
   *  
   * </pre>
   */
  public synchronized DmsDocument getDocumentByNameParentID(String name, Integer parentID) throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    DmsDocument tmpDmsDocument = new DmsDocument();
    
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE,A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF,A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        sqlStat.append("WHERE  A.DOCUMENT_NAME = ? AND A.PARENT_ID = ? AND A.RECORD_STATUS = ? ");
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, name);
        this.setPrepareStatement(preStat, 2, parentID);
        this.setPrepareStatement(preStat, 3, GlobalConstant.RECORD_STATUS_ACTIVE);
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        rs = preStat.executeQuery();
        
        if (rs.next()) {
          tmpDmsDocument = parseObjectFromResultSet(rs);
          return (tmpDmsDocument);
        } else {
          return (null);
        }
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle,
            sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  /**
   * Gets the document by the document name and parent D
   * 
   * 
   * @param parentID the parent Id
   * @return the DmsDocument object matched, null if no matched.
   * @throws ApplicationException
   * <pre>
   * 
   *            ApplicationException with the following message codes will be thrown
   *            ErrorConstant.ErrorConstant.DB_GENERAL_ERROR - General caught SQLException
   *            ErrorConstant.DB_SELECT_ERROR - All kind of caught Exception
   *  
   * </pre>
   */
  public synchronized DmsDocument getDocumentByParentID(String name, Integer parentID) throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    DmsDocument tmpDmsDocument = new DmsDocument();
    
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE,A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF,A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        sqlStat.append("WHERE  A.ID = ? AND A.RECORD_STATUS = ? ");
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        //this.setPrepareStatement(preStat, 1, name);
        this.setPrepareStatement(preStat, 1, parentID);
        this.setPrepareStatement(preStat, 2, GlobalConstant.RECORD_STATUS_ACTIVE);
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        rs = preStat.executeQuery();
        
        if (rs.next()) {
          tmpDmsDocument = parseObjectFromResultSet(rs);
          return (tmpDmsDocument);
        } else {
          return (null);
        }
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle,
            sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  /**
   * Gets the document by the document name and parent D
   * 
   * @param name the document name
   * @param parentID the parent Id
   * @return the DmsDocument object matched, null if no matched.
   * @throws ApplicationException
   * <pre>
   * 
   *            ApplicationException with the following message codes will be thrown
   *            ErrorConstant.ErrorConstant.DB_GENERAL_ERROR - General caught SQLException
   *            ErrorConstant.DB_SELECT_ERROR - All kind of caught Exception
   *  
   * </pre>
   */
  public synchronized DmsDocument getDocumentByNameParentID(String name, Integer parentID,String documentType) throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    DmsDocument tmpDmsDocument = new DmsDocument();
    
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE,A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF,A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        sqlStat.append("WHERE  A.DOCUMENT_NAME = ? AND A.PARENT_ID = ? AND A.RECORD_STATUS = ? ");
        if("*".equals(documentType)){
          sqlStat.append(" AND A.DOCUMENT_TYPE <> 'L' ");
        }else{
          sqlStat.append(" AND A.DOCUMENT_TYPE = 'L' ");          
        }
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, name);
        this.setPrepareStatement(preStat, 2, parentID);
        this.setPrepareStatement(preStat, 3, GlobalConstant.RECORD_STATUS_ACTIVE);
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        rs = preStat.executeQuery();
        
        if (rs.next()) {
          tmpDmsDocument = parseObjectFromResultSet(rs);
          return (tmpDmsDocument);
        } else {
          return (null);
        }
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle,
            sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  

  /**
   * Gets the list of the document that match the search criteria specified in the searchForm and under root specified 
   * the list of rootIDs.
   * <P>
   * If you pass in a ListDmsDocumentForm
   * object, you can search by invoke the setter method of the following properties,
   * </P>
   * <table border=1 cellspacing=1 cellpadding=1>
   * <tr><th>Property</th><th>Description</th><th>Possible values</th></tr>
   * <tr><td>document name</td><td>document name</td><td>any string value</td>/tr>
   * <tr><td>EffectiveStartDate</td><td>effective start date</td><td>date in format {@link com.dcivision.framework#DB_DATETIME_FORMAT} </td></tr>
   * <tr><td>EffectiveEndDate</td><td>effective end date<td><td>date in format {@link com.dcivision.framework#DB_DATETIME_FORMAT} </td></tr>
   * <tr><td>CreateDate</td><td>Create Date</td><td>date in format {@link com.dcivision.framework#DB_DATETIME_FORMAT} </td></tr>
   * <tr><td>UpdateDate</td><td>Update Date</td><td>date in format {@link com.dcivision.framework#DB_DATETIME_FORMAT} </td></tr>
   * <tr><td>DocumentType</td><td>document type</td><td>{@link com.dcivision.dms.bean.DmsDocument#DOCUMENT_TYPE},
   *                                                    {@link com.dcivision.dms.bean.DmsDocument#COMPOUND_DOC_TYPE},
   *                                                    {@link com.dcivision.dms.bean.DmsDocument#DOCUMENT_LINK},
   *                                                    {@link com.dcivision.dms.bean.DmsDocument#FOLDER_TYPE} 
   *                                                </td></tr>
   * <tr><td>ReferenceNo</td><td>Document reference no</td><td>any string value</td></tr>
   * <tr><td>Priority</td><td>Document Priority</td><td>{@link com.dcivision.framework.GlobalConstant#PRIORITY_HIGH},{@link com.dcivision.framework.GlobalConstant#PRIORITY_LOW},{@link com.dcivision.framework.GlobalConstant#PRIORITY_MEDIUM}</td></tr>
   * <tr><td>Description</td><td>Document description</td><td>any string values</td></tr>
   * <tr><td>UserDef1 (1-10)</td><td>User defined value 1-10 (default profile values)</td><td>any string values</td></tr>
   * <tr><td>UserDef1To(1-10)</td><td>uppper range limit for numeric or date type of user defined values</td><td>any string values</td></tr>
   * <tr><td>UserDefinedFieldID</td><td>document profile</td><td>{@link com.dcivision.framework.bean.SysUserDefinedIndex#getID()}</td></tr>
   * <tr><td>DocumentDetails</td><td>List of Document Detail object</td><td>&nbsp;</td></tr>
   * <tr><td colspan='3'>the document detail object(user profile field value) 
   *                    <br>properties set for searching as follow:</td></tr>
   * <tr><td>FieldValue</td><td>String type document detail 
   *                           <br>{@link com.dcivision.framework.bean.SysUserDefinedIndexDetail#STRING_FIELD}</td><td>any string values</td></tr>
   * <tr><td>NumericValue</td><td>Numeric type document detail
   *                             <br>{@link com.dcivision.framework.bean.SysUserDefinedIndex#NUMBER_FIELD}</td><td>any string values</td></tr>
   *<tr><td>ToNumericValue</td><td>upper range limit Numeric type document detail</td><td>any string values in numeric format</td></tr>
   *<tr><td>DateValue</td><td>Date type document detail
   *                             <br>{@link com.dcivision.framework.bean.SysUserDefinedIndex#DATE_FIELD}</td><td>any string values</td></tr>
   *<tr><td>ToDateValue</td><td>upper range limit Date type document detail</td><td>any string values in Date format {@link com.dcivision.framework#DB_DATETIME_FORMAT}</td></tr>
   * </table>
   * 
   * <PRE>
   * 
   * Each of the search properties contains 2 search options i.e. for Description field
   *    options                   Usage
   * 1. DescriptionExactMatch -   Exact match the search criteria   
   * 2. DescriptionOption     -   Specifiy the Operand with other search fields(And/OR)
   * 
   * Special search function also support in search
   * 1. relational search - any string type searching, if it is chinese char(s), both the simplified chinese or traditional chinese char also be searched
   *                        if SystemParameterConstant.DMS_RELATIONAL_WORD_ENABLE set to true in SYS_PARAMETER table, 
   *                        the user defined relational word also be searched.
   * 
   * 2. range search - special char (>=, >, AND, OR, NOT) in the search field, extra search criteria is added. e.g.
   *                   search document name as ">= 1000001.tif", the document name greater than or equal to 1000001.tif will be searched.
   * 
   * </PRE>
   * @param searchForm the ListDmsDocumentForm object
   * @param rootIDs the list of the root ID to limit the searched document under the given root
   * @return List the document(s) matched the search criteria
   * @throws ApplicationException
   
   * <pre>
   * 
   *            ApplicationException with the following message codes will be thrown
   *            ErrorConstant.ErrorConstant.DB_GENERAL_ERROR - General caught SQLException
   *            ErrorConstant.DB_SELECT_ERROR - All kind of caught Exception
   *  
   * </pre>
   * 
   * 
   */
  public synchronized List getAdvanceSearchList(AbstractSearchForm searchForm, List rootIDs) throws ApplicationException {
    PreparedStatement preStat = null;
    PreparedStatement preStatCnt = null;
    ResultSet rs = null;
    ResultSet rsCnt = null;
    StringBuffer sqlStat = new StringBuffer();
    StringBuffer sqlStatCnt = new StringBuffer();
    List result = new ArrayList();
    int totalNumOfRecord = 0;
    int rowLoopCnt = 0;
    int startOffset = TextUtility.parseInteger(searchForm.getCurStartRowNo());
    int pageSize = TextUtility.parseInteger(searchForm.getPageOffset());
    
    ListDmsDocumentForm docSearchForm = (ListDmsDocumentForm) searchForm;
    List docDetailList = docSearchForm.getDocumentDetails();
    HashMap mFieldMap = new HashMap();
    
    Timestamp currTime = Utility.getCurrentTimestamp();
    Timestamp oneDayBeforeCurrTime = Utility.addDay(currTime, -1);
    DocumentRetrievalManager docRetrievalManager = new DocumentRetrievalManager(sessionContainer, dbConn);
    //Default profile display.
    int totalFieldCount = Integer.parseInt(com.dcivision.framework.SystemParameterFactory.getSystemParameter(com.dcivision.framework.SystemParameterConstant.DMS_DEFAULT_PROFILE_FIELD_COUNT));
    
    synchronized (dbConn) {
      try {
        //SQL
        sqlStat.append("SELECT DISTINCT(D.ID), ");
        sqlStat.append("D.DOCUMENT_NAME, D.DOCUMENT_TYPE, D.PARENT_ID, D.ROOT_ID, D.PRIORITY, D.CREATE_TYPE, D.EFFECTIVE_START_DATE, D.EFFECTIVE_END_DATE, D.REMINDER_AMOUNT, D.REMINDER_TYPE, D.NOTIFICATION_WAY, D.OWNER_ID, D.REFERENCE_NO, D.DESCRIPTION, D.ITEM_SIZE, D.ITEM_STATUS, D.CHECKOUT_ID, D.ALERT_EDIT_ID, D.ALERT_INVITE_ID, D.EXT_REF,D.USER_DEF_1, D.USER_DEF_2, D.USER_DEF_3, D.USER_DEF_4, D.USER_DEF_5, D.USER_DEF_6, D.USER_DEF_7, D.USER_DEF_8, D.USER_DEF_9, D.USER_DEF_10, D.RECORD_STATUS, D.UPDATE_COUNT, D.CREATOR_ID, D.CREATE_DATE, D.UPDATER_ID, D.UPDATE_DATE ");
        
        if (!Utility.isEmpty(docSearchForm.getUserDefinedFieldID())) {
          sqlStat.append(", DI.USER_DEFINED_FIELD_ID ");
        }
        sqlStat.append("FROM  ");
//      table1 LEFT JOIN table2 ON table1.id=table2.id
        if (!Utility.isEmpty(docSearchForm.getUserDefinedFieldID())) {
          
          sqlStat.append(" DMS_DOCUMENT D LEFT JOIN DMS_DOCUMENT_INDEX DI ON D.ID=DI.DOCUMENT_ID ");
        } else {
          
          sqlStat.append(" DMS_DOCUMENT D ");
        }
        
        sqlStat.append("WHERE  D.RECORD_STATUS = ? ");
        
        // TIF_ANNOTATION_TYPE / ORIGINSLITY_EMAIL_TYPE should no display in result list(EIP-1296 lee 07/01/18)
        sqlStat.append(" AND D.DOCUMENT_TYPE <> '"+DmsDocument.TIF_ANNOTATION_TYPE+"' ");
        sqlStat.append(" AND D.DOCUMENT_TYPE <> '"+DmsDocument.ORIGINSLITY_EMAIL_TYPE+"' ");
        
        //to ensure no root folder is selected
        sqlStat.append(" AND D.PARENT_ID <> 0 ");
        
        int tmpCounter = 0; //purpose in checking the WHERE statment
        
        // if (!Utility.isEmpty(docSearchForm.getUserDefinedFieldID())) {
        //   sqlStat.append(" AND D.ID = DI.DOCUMENT_ID");
        // }
        
        sqlStat.append("  AND (");
        
        int startPos = sqlStat.length(); //used to record the criteria
        String outerCriteria = "";
        if (DmsOperationConstant.ATTR_NEST_FILTER_OPERATION.equals(docSearchForm.getOpMode()) &&
            !Utility.isEmpty(docSearchForm.getOuterCriteria())) {
          outerCriteria = docSearchForm.getOuterCriteria();
          
        } else if (DmsOperationConstant.ATTR_EXPORT_OPERATION.equals(docSearchForm.getOpMode()) ||
            DmsOperationConstant.ATTR_COMBINE_TIFF_OPERATION.equals(docSearchForm.getOpMode())) {
          if (DmsOperationConstant.ATTR_NEST_FILTER_OPERATION.equals(docSearchForm.getPrvOpMode()) &&
              !Utility.isEmpty(docSearchForm.getOuterCriteria())) {
            outerCriteria = docSearchForm.getOuterCriteria();
          }
        }
        
        int repe = 0;
        String relationDocumentName="";
        String name="";
        DmsRelationalWord dmsRelationalWord=new DmsRelationalWord();
        String tmp[] = null;
        String sName=TextUtility.convert(docSearchForm.getDocumentName());//convert big5 to gb or gb to big5
        String documentName=docSearchForm.getDocumentName();
        DmsRelationalWordDAObject dmsRelationalWordDaobject = new DmsRelationalWordDAObject(sessionContainer, dbConn);
        //relational word is false or true
        boolean isRelationWord = SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_RELATIONAL_WORD_ENABLE);
        name=docSearchForm.getDocumentName();
        if (!Utility.isEmpty(docSearchForm.getDocumentName())) {
          
          HashMap mResult=null;
          tmpCounter++;
          if(!TextUtility.checkContainsOperandChar(docSearchForm.getDocumentName())){
            name=sName + " OR " +documentName;
            if(isRelationWord){//relatioanal word
              List relationalDocumentNameList = dmsRelationalWordDaobject.getRelationalWordListByKeyWord(docSearchForm.getDocumentName());
              for(int i=0;i<relationalDocumentNameList.size();i++){
                dmsRelationalWord = (DmsRelationalWord)relationalDocumentNameList.get(i);
                relationDocumentName = dmsRelationalWord.getWord();
                name += " OR " + TextUtility.convert(relationDocumentName) + " OR " +relationDocumentName ;
              }
            }
          }
          
          mResult = getCriteriaCombination("D.DOCUMENT_NAME",
              name,
              docSearchForm.getDocumentNameExactMatch());
          
          
          
          sqlStat.append(mResult.get("SQL"));
          
          repe += TextUtility.parseInteger( (String) mResult.get("?"));
          mFieldMap.put("DOCUMENT_NAME",mResult.get("fieldResult"));
          
        }
        
        
        //the personal folder should not be shown in the search case
        
        if (!Utility.isEmpty(docSearchForm.getEffectiveStartDate()) ||
            !Utility.isEmpty(docSearchForm.getEffectiveEndDate())) {
          tmpCounter++;
          if (tmpCounter > 1) {
            sqlStat.append(" " + docSearchForm.getEffectiveDateOption() + " ");
          }
          
          if (DataSourceFactory.getDatabaseType() == DataSourceFactory.DB_ORACLE) {
            
            if ( (!Utility.isEmpty(docSearchForm.getEffectiveStartDate())) &&
                (!Utility.isEmpty(docSearchForm.getEffectiveEndDate()))) {
              sqlStat.append(" (D.EFFECTIVE_START_DATE < = TO_DATE('" + TextUtility.dbDateAdder(docSearchForm.getEffectiveEndDate(), 1) + "','"+ "YYYY-MM-DD HH24:MI:SS" +"') AND D.EFFECTIVE_END_DATE > TO_DATE('" + docSearchForm.getEffectiveStartDate() +
                  "','" + "YYYY-MM-DD HH24:MI:SS" +"')) ");
            } else if ( (!Utility.isEmpty(docSearchForm.getEffectiveStartDate())) && //only first value entered
                (Utility.isEmpty(docSearchForm.getEffectiveEndDate()))) {
              sqlStat.append(" (D.EFFECTIVE_START_DATE >= TO_DATE('" + docSearchForm.getEffectiveStartDate() + "','"+"YYYY-MM-DD HH24:MI:SS"+"' )) ");
            } else if ( (Utility.isEmpty(docSearchForm.getEffectiveStartDate())) && //only 2nd value entered
                (!Utility.isEmpty(docSearchForm.getEffectiveEndDate()))) {
              sqlStat.append(" (D.EFFECTIVE_END_DATE < TO_DATE('" + TextUtility.dbDateAdder(docSearchForm.getEffectiveEndDate(), 1) + "','"+"YYYY-MM-DD HH24:MI:SS"+"' )) ");
            }
          }else{
            if ( (!Utility.isEmpty(docSearchForm.getEffectiveStartDate())) &&
                (!Utility.isEmpty(docSearchForm.getEffectiveEndDate()))) {
              sqlStat.append(" (D.EFFECTIVE_START_DATE < '" + TextUtility.dbDateAdder(docSearchForm.getEffectiveEndDate(), 1) + "' AND D.EFFECTIVE_END_DATE > '" + docSearchForm.getEffectiveStartDate() +
              "' ) ");
            } else if ( (!Utility.isEmpty(docSearchForm.getEffectiveStartDate())) && //only first value entered
                (Utility.isEmpty(docSearchForm.getEffectiveEndDate()))) {
              sqlStat.append(" (D.EFFECTIVE_START_DATE >= '" + docSearchForm.getEffectiveStartDate() + "' ) ");
            } else if ( (Utility.isEmpty(docSearchForm.getEffectiveStartDate())) && //only 2nd value entered
                (!Utility.isEmpty(docSearchForm.getEffectiveEndDate()))) {
              sqlStat.append(" (D.EFFECTIVE_END_DATE < '" + TextUtility.dbDateAdder(docSearchForm.getEffectiveEndDate(), 1) + "' ) ");
            }
          }
          //personal folder will not shown as result
          Integer userID = sessionContainer.getUserRecordID();
          DmsRootDAObject rootDAO = new DmsRootDAObject(sessionContainer, dbConn);
          List rootList = rootDAO.getRootByOwnerIDAndType(userID, DmsRoot.PERSONAL_ROOT, GlobalConstant.RECORD_STATUS_ACTIVE);
          DmsRoot rootPoint = null;
          if (!Utility.isEmpty(rootList)) {
            rootPoint = (DmsRoot) rootList.get(0);
            sqlStat.append(" AND (D.ROOT_ID <>" + rootPoint.getID() + ") ");
          }
        }
        
        //search document by the create date and update date
        
        if (!Utility.isEmpty(docSearchForm.getCreateDate()) ||
            !Utility.isEmpty(docSearchForm.getCreateToDate())) {
          tmpCounter++;
          
          if (tmpCounter > 1) {
            sqlStat.append(" " + docSearchForm.getCreateDateOption() + " ");
          }
          
          if (DataSourceFactory.getDatabaseType() == DataSourceFactory.DB_ORACLE) {
            if ( (!Utility.isEmpty(docSearchForm.getCreateDate())) && (!Utility.isEmpty(docSearchForm.getCreateToDate()))) {
              sqlStat.append(" (D.CREATE_DATE >= TO_DATE('" + docSearchForm.getCreateDate() + "','"+ "YYYY-MM-DD HH24:MI:SS" +"') AND D.CREATE_DATE < TO_DATE('" + TextUtility.dbDateAdder(docSearchForm.getCreateToDate(), 1) + "','" + "YYYY-MM-DD HH24:MI:SS" +"')) ");
            } else if ( (!Utility.isEmpty(docSearchForm.getCreateDate())) && (Utility.isEmpty(docSearchForm.getCreateToDate()))) {
              sqlStat.append(" (D.CREATE_DATE >= TO_DATE('" + docSearchForm.getCreateDate() + "','"+"YYYY-MM-DD HH24:MI:SS"+"')) ");
            } else if ( (Utility.isEmpty(docSearchForm.getCreateDate())) && (!Utility.isEmpty(docSearchForm.getCreateToDate()))) {
              sqlStat.append(" (D.CREATE_DATE < TO_DATE('" + TextUtility.dbDateAdder(docSearchForm.getCreateToDate(), 1) + "','"+"YYYY-MM-DD HH24:MI:SS"+"')) ");
            }
          }else{
            if ( (!Utility.isEmpty(docSearchForm.getCreateDate())) && (!Utility.isEmpty(docSearchForm.getCreateToDate()))) {
              sqlStat.append(" (D.CREATE_DATE >= '" + docSearchForm.getCreateDate() + "' AND D.CREATE_DATE < '" + TextUtility.dbDateAdder(docSearchForm.getCreateToDate(), 1) + "') ");
            } else if ( (!Utility.isEmpty(docSearchForm.getCreateDate())) && (Utility.isEmpty(docSearchForm.getCreateToDate()))) {
              sqlStat.append(" (D.CREATE_DATE >= '" + docSearchForm.getCreateDate() + "') ");
            } else if ( (Utility.isEmpty(docSearchForm.getCreateDate())) && (!Utility.isEmpty(docSearchForm.getCreateToDate()))) {
              sqlStat.append(" (D.CREATE_DATE < '" + TextUtility.dbDateAdder(docSearchForm.getCreateToDate(), 1) + "') ");
            }
            
            
          }
          
        }
        
        if (!Utility.isEmpty(docSearchForm.getUpdateDate()) ||
            !Utility.isEmpty(docSearchForm.getUpdateToDate())) {
          tmpCounter++;
          
          if (tmpCounter > 1) {
            sqlStat.append(" " + docSearchForm.getUpdateDateOption() + " ");
          }
          
          if (DataSourceFactory.getDatabaseType() == DataSourceFactory.DB_ORACLE) {
            if ( (!Utility.isEmpty(docSearchForm.getUpdateDate())) && (!Utility.isEmpty(docSearchForm.getUpdateToDate()))) {
              sqlStat.append(" (D.UPDATE_DATE >= TO_DATE('" + docSearchForm.getUpdateDate() + "','"+ "YYYY-MM-DD HH24:MI:SS" + "') AND D.UPDATE_DATE < TO_DATE('" + TextUtility.dbDateAdder(docSearchForm.getUpdateToDate(), 1) + "','"+"YYYY-MM-DD HH24:MI:SS"+"')) ");
            } else if ( (!Utility.isEmpty(docSearchForm.getUpdateDate())) && (Utility.isEmpty(docSearchForm.getUpdateToDate()))) {
              sqlStat.append(" (D.UPDATE_DATE >= TO_DATE('" + docSearchForm.getUpdateDate() + "','"+ "YYYY-MM-DD HH24:MI:SS" +"')) ");
            } else if ( (Utility.isEmpty(docSearchForm.getUpdateDate())) && (!Utility.isEmpty(docSearchForm.getUpdateToDate()))) {
              sqlStat.append(" (D.UPDATE_DATE < TO_DATE('" + TextUtility.dbDateAdder(docSearchForm.getUpdateToDate(), 1) + "','"+ "YYYY-MM-DD HH24:MI:SS"+"')) ");
            }
          }else{
            if ( (!Utility.isEmpty(docSearchForm.getUpdateDate())) && (!Utility.isEmpty(docSearchForm.getUpdateToDate()))) {
              sqlStat.append(" (D.UPDATE_DATE >= '" + docSearchForm.getUpdateDate() + "' AND D.UPDATE_DATE < '" + TextUtility.dbDateAdder(docSearchForm.getUpdateToDate(), 1) + "') ");
            } else if ( (!Utility.isEmpty(docSearchForm.getUpdateDate())) && (Utility.isEmpty(docSearchForm.getUpdateToDate()))) {
              sqlStat.append(" (D.UPDATE_DATE >= '" + docSearchForm.getUpdateDate() + "') ");
            } else if ( (Utility.isEmpty(docSearchForm.getUpdateDate())) && (!Utility.isEmpty(docSearchForm.getUpdateToDate()))) {
              sqlStat.append(" (D.UPDATE_DATE < '" + TextUtility.dbDateAdder(docSearchForm.getUpdateToDate(), 1) + "') ");
            }
          }
          
        }
        
        if (!Utility.isEmpty(docSearchForm.getDocumentType())) {
          tmpCounter++;
          if (tmpCounter > 1) {
            sqlStat.append(" " + docSearchForm.getDocumentTypeOption() + " ");
          }
          String documentType = docSearchForm.getDocumentType();
          String fieldValues = "";
          for( int i = 0 ; i < documentType.length() ; i ++ ) {
            fieldValues += documentType.charAt(i) + " ";
            if( i != documentType.length()-1) {
              fieldValues += "OR ";
            }
          }
          HashMap mResult = getCriteriaCombination("D.DOCUMENT_TYPE",
              fieldValues,
              true);
          sqlStat.append(mResult.get("SQL"));
          repe += TextUtility.parseInteger( (String) mResult.get("?"));
          mFieldMap.put("DOCUMENT_TYPE", mResult.get("fieldResult"));
        }
        
        if (!Utility.isEmpty(docSearchForm.getSearchPriority())) {
          tmpCounter++;
          if (tmpCounter > 1) {
            sqlStat.append(" " + docSearchForm.getPriorityOption() + " ");
          }
          HashMap mResult = getCriteriaCombination("D.PRIORITY",
              Utility.genericLogicSql(docSearchForm.getSearchPriority(),"OR"),
              true);
          sqlStat.append(mResult.get("SQL"));
          repe += TextUtility.parseInteger( (String) mResult.get("?"));
          mFieldMap.put("PRIORITY", mResult.get("fieldResult"));
          
        }
        
        if (!Utility.isEmpty(docSearchForm.getReferenceNo())) {
          tmpCounter++;
          if (tmpCounter > 1) {
            sqlStat.append(" " + docSearchForm.getReferenceNoOption() + " ");
          }
          HashMap mResult = getCriteriaCombination("D.REFERENCE_NO",
              docSearchForm.getReferenceNo(),
              docSearchForm.getReferenceNoExactMatch());
          sqlStat.append(mResult.get("SQL"));
          repe += TextUtility.parseInteger( (String) mResult.get("?"));
          mFieldMap.put("REFERENCE_NO", mResult.get("fieldResult"));
        }
        
        if (!Utility.isEmpty(docSearchForm.getDescription())) {
          
          String sDescription=TextUtility.convert(docSearchForm.getDescription());//convert big5 to gb or gb to big5
          String description=docSearchForm.getDescription();
          String nDescription=description;
          tmpCounter++;
          
          
          
          if (tmpCounter > 1) {
            sqlStat.append(" " + docSearchForm.getDescriptionOption() + " ");
          }
          
          if(!TextUtility.checkContainsOperandChar(docSearchForm.getDescription())){
            nDescription=sDescription + " OR " + description;
            
            if(isRelationWord){//relatioanal word
              List relationalDescriptionList = dmsRelationalWordDaobject.getRelationalWordListByKeyWord(docSearchForm.getDescription());
              for(int i=0;i<relationalDescriptionList.size();i++){
                dmsRelationalWord = (DmsRelationalWord)relationalDescriptionList.get(i);
                String relationDescription = dmsRelationalWord.getWord();
                nDescription += " OR " + TextUtility.convert(relationDescription) + " OR " +relationDescription ;
              }
            }
          }
          
          HashMap mResult = getCriteriaCombination("D.DESCRIPTION",
              nDescription,
              docSearchForm.getDescriptionExactMatch());
          sqlStat.append(mResult.get("SQL"));
          repe += TextUtility.parseInteger( (String) mResult.get("?"));
          mFieldMap.put("DESCRIPTION", mResult.get("fieldResult"));
        }
        
        if (!Utility.isEmpty(docSearchForm.getCreatorID())) {
          tmpCounter++;
          if (tmpCounter > 1) {
            sqlStat.append(" " + docSearchForm.getCreatorOption() + " ");
          }
          HashMap mResult = getCriteriaCombination("D.CREATOR_ID",
              docSearchForm.getCreatorID(),
              true);
          sqlStat.append(mResult.get("SQL"));
          repe += TextUtility.parseInteger( (String) mResult.get("?"));
          mFieldMap.put("CREATOR_ID", mResult.get("fieldResult"));
        }
        
        //iterate userDef1 to userDef10 using reflection
        for(int udfIdx = 1 ; udfIdx<=totalFieldCount ; udfIdx++){
          Class cls = Class.forName(ListDmsDocumentForm.class.getName());
          Method userDefMethod = cls.getMethod("getUserDef"+udfIdx,null);
          String userDefFrom = (String)userDefMethod.invoke(docSearchForm, null);
          Method userDefToMethod = cls.getMethod("getUserDef"+udfIdx+"To",null);
          String userDefTo = (String)userDefToMethod.invoke(docSearchForm, null);
          Method userDefOptionMethod = cls.getMethod("getUserDef"+udfIdx+"Option",null);
          String userDefOption = (String)userDefOptionMethod.invoke(docSearchForm, null);
          
          Method userDefDataTypeMethod = cls.getMethod("getUserDef"+udfIdx+"DataType",null);
          String userDefDataType = (String)userDefDataTypeMethod.invoke(docSearchForm, null);
          
          Method userDefExactMatchMethod = cls.getMethod("getUserDef"+udfIdx+"ExactMatch",null);
          
          boolean userDefExactMatch = ((Boolean)userDefExactMatchMethod.invoke(docSearchForm, null)).booleanValue();         
          if ( (!Utility.isEmpty(userDefFrom)) || (!Utility.isEmpty(userDefTo))) {
            tmpCounter++;
            if (tmpCounter > 1) {
              sqlStat.append(" " + userDefOption + " ");
            }
            
            if (DmsDefaultProfileSetting.FIELD_TYPE_DATE.equals(userDefDataType)) {
              if ( (!Utility.isEmpty(userDefFrom)) && (!Utility.isEmpty(userDefTo))) {
                sqlStat.append(" (D.USER_DEF_" + udfIdx + " >= '" + userDefFrom + "' AND D.USER_DEF_" + udfIdx + " <= '" + userDefTo + "' ) ");
              }else{              
                sqlStat.append("(");
                if ( !Utility.isEmpty(userDefFrom) ) { //only first value entered               
                  sqlStat.append(" D.USER_DEF_" + udfIdx + " >= '" + userDefFrom + "' ");               
                }else{ //only 2nd value entered
                  sqlStat.append(" D.USER_DEF_" + udfIdx + "  <= '" + userDefTo + "' ");
                }
                if (DataSourceFactory.getDatabaseType() == DataSourceFactory.DB_ORACLE) {              
                  sqlStat.append(" AND LENGTH(D.USER_DEF_" + udfIdx + ") > 0 ");              
                }else{
                  sqlStat.append(" AND D.USER_DEF_" + udfIdx + " <> '' ");
                }
                sqlStat.append(")");
              }
            } else {
              String sUserDef=userDefFrom;
              String getUserDef=TextUtility.convert(sUserDef);//convert big5 to gb or gb to big5
              String sGetUserDef=sUserDef;
              if(!TextUtility.checkContainsOperandChar(userDefFrom)){
                sGetUserDef = sUserDef + " OR " + getUserDef;
                if(isRelationWord){  //relatioanal word
                  List relationalUserDefList = dmsRelationalWordDaobject.getRelationalWordListByKeyWord(userDefFrom);
                  for(int i=0;i<relationalUserDefList.size();i++){
                    dmsRelationalWord = (DmsRelationalWord)relationalUserDefList.get(i);
                    String relationUserDef = dmsRelationalWord.getWord();
                    sGetUserDef += " OR " + TextUtility.convert(relationUserDef) + " OR " +relationUserDef ;
                  }
                }
              }
              
              HashMap mResult = getCriteriaCombination("D.USER_DEF_" + udfIdx, sGetUserDef, userDefExactMatch);
              sqlStat.append(mResult.get("SQL"));
              repe += TextUtility.parseInteger( (String) mResult.get("?"));
              mFieldMap.put("USER_DEF_" + udfIdx, mResult.get("fieldResult"));
            }
          }
        }
        
        if (!Utility.isEmpty(docSearchForm.getUserDefinedFieldID())) {
//        int tempCounter = 0;
          tmpCounter++;
          if (tmpCounter > 1) {
            sqlStat.append(" " + docSearchForm.getUserDefinedFieldOption() + " ");
          }
          
//        DmsDocumentDetail docDetail = (DmsDocumentDetail) docDetailList.get(0);
          
          log.debug("the user defined field option:" + docSearchForm.getUserDefinedFieldOption());
          //sqlStat.append(" ( DD.USER_DEFINED_FIELD_ID =" + docSearchForm.getUserDefinedFieldID());
          sqlStat.append(" ( DI.USER_DEFINED_FIELD_ID =" + docSearchForm.getUserDefinedFieldID());
          
          int fieldTmpCount = 0;
          int a = 0;
          DmsDocumentDetail docDetail = new DmsDocumentDetail();
          
          docDetailList = docRetrievalManager.sortDocDetailList(docDetailList);
          
          for (int i = 0; i < docDetailList.size(); i++) {
            docDetail = (DmsDocumentDetail) docDetailList.get(i);
            int pos = 0;
            //pos=docRetrievalManager.getUDFDetailPos(TextUtility.parseIntegerObj(docSearchForm.getUserDefinedFieldID()),docDetail.getUserDefinedFieldDetailID());
            pos = i + 1;
            
            log.debug("the field type is:"+docDetail.getFieldType().toString());
            if (pos > 0) {
              if (!Utility.isEmpty(docDetail.getFieldValue()) || docDetail.getDateValue() != null ||
                  docDetail.getToDateValue() != null || docDetail.getNumericValue() != null ||
                  docDetail.getToNumericValue() != null) {
                fieldTmpCount++;
                a++;
                //if (a == 1)  sqlStat.append(" AND ");
                //if (fieldTmpCount > 1) {
                sqlStat.append(" " + docDetail.getSearchOption() + " ");
                //}
                sqlStat.append(" ( ");
                // sqlStat.append(" ( DI.USER_DEFINED_FIELD_DETAIL_ID = " + docDetail.getUserDefinedFieldDetailID().toString());
                // sqlStat.append(" AND ");
                
                if ( (SysUserDefinedIndexDetail.STRING_FIELD.equals(docDetail.getFieldType()) ||
                    docDetail.getFieldType().startsWith("CUST")) && !Utility.isEmpty(docDetail.getFieldValue())) {
                  
                  String sFieldValue=docDetail.getFieldValue();
                  String sValue=TextUtility.convert(sFieldValue);//convert big5 to gb or gb to big5
                  String sGetFieldValue=sFieldValue;
                  if(!TextUtility.checkContainsOperandChar(docDetail.getFieldValue())){
                    sGetFieldValue=sFieldValue+" OR "+sValue;
                    if(isRelationWord){//relatioanal word
                      List relationalFieldValueList = dmsRelationalWordDaobject.getRelationalWordListByKeyWord(docDetail.getFieldValue());
                      for( int n=0;n<relationalFieldValueList.size();n++){
                        dmsRelationalWord = (DmsRelationalWord)relationalFieldValueList.get(n);
                        String relationFieldValue = dmsRelationalWord.getWord();
                        sGetFieldValue += " OR " + TextUtility.convert(relationFieldValue) + " OR " +relationFieldValue ;
                      }
                    }
                  }
                  
                  HashMap mResult = getCriteriaCombination("DI.INDEX_" + pos, sGetFieldValue, docDetail.getExactMatch());
                  sqlStat.append(mResult.get("SQL"));
                  repe += TextUtility.parseInteger( (String) mResult.get("?"));
                  
                  List tmpList = (List) mResult.get("fieldResult");
                  mFieldMap.put("UDF_DETAIL_" + docDetail.getUserDefinedFieldDetailID() + "_FIELDVALUE", mResult.get("fieldResult"));
                  
                } else if (SysUserDefinedIndexDetail.FIELD_TYPE_SELECT_DATABASE.equals(docDetail.getFieldType()) && !Utility.isEmpty(docDetail.getFieldValue())) {
                  
                  String sFieldValue=docDetail.getFieldValue();
                  String sValue=TextUtility.convert(sFieldValue);//convert big5 to gb or gb to big5
                  String sGetFieldValue=sFieldValue;
                  if(!TextUtility.checkContainsOperandChar(docDetail.getFieldValue())){
                    sGetFieldValue=sFieldValue+" OR "+sValue;
                    if(isRelationWord){//relatioanal word
                      List relationalFieldValueList = dmsRelationalWordDaobject.getRelationalWordListByKeyWord(docDetail.getFieldValue());
                      for( int n=0;n<relationalFieldValueList.size();n++){
                        dmsRelationalWord = (DmsRelationalWord)relationalFieldValueList.get(n);
                        String relationFieldValue = dmsRelationalWord.getWord();
                        sGetFieldValue += " OR " + TextUtility.convert(relationFieldValue) + " OR " +relationFieldValue ;
                      }
                    }
                  }
                  
                  HashMap mResult = getCriteriaCombination("DI.INDEX_" + pos, sGetFieldValue, true);
                  sqlStat.append(mResult.get("SQL"));
                  repe += TextUtility.parseInteger( (String) mResult.get("?"));
                  
                  List tmpList = (List) mResult.get("fieldResult");
                  mFieldMap.put("UDF_DETAIL_" + docDetail.getUserDefinedFieldDetailID() + "_FIELDVALUE", mResult.get("fieldResult"));
                  
                } else if (SysUserDefinedIndexDetail.NUMBER_FIELD.equals(docDetail.getFieldType())) { //number value
                  
                  log.debug("the numberic value:"+docDetail.getNumericValue());
                  if (docDetail.getNumericValue() != null && docDetail.getToNumericValue() != null) {
                    sqlStat.append(" (DI.INDEX_" + pos + ">= " + docDetail.getNumericValue() + " AND DI.INDEX_" + pos + " <= " +
                        docDetail.getToNumericValue() + " ) ");
                  } else if (docDetail.getNumericValue() != null && docDetail.getToNumericValue() == null) { //only first value entered
                    sqlStat.append(" (DI.INDEX_" + pos + " >= " + docDetail.getNumericValue() + " ) ");
                  } else if (docDetail.getNumericValue() == null && docDetail.getToNumericValue() != null) { //only 2nd value entered
                    sqlStat.append(" (DI.INDEX_" + pos + " <= " + docDetail.getToNumericValue() + " ) ");
                  }
                  
                } else if (SysUserDefinedIndexDetail.DATE_FIELD.equals(docDetail. //Date range
                    getFieldType())) {
                  
                  if (docDetail.getDateValue() != null && docDetail.getToDateValue() != null) {
                    //sqlStat.append(" (DI.INDEX_" + pos + " >= '" + DateField.dateToString(docDetail.getDateValue()) + "' AND DI.INDEX_" + pos + " <= '" +
                    //               DateField.dateToString(docDetail.getToDateValue()) + "' ) ");
                    sqlStat.append(" (DI.INDEX_" + pos + " >= '" + TextUtility.formatTimestampToIndex(docDetail.getDateValue()) + "' AND DI.INDEX_" + pos + " <= '" +
                        TextUtility.formatTimestampToIndex(docDetail.getToDateValue()) + "' ) ");
                  } else if (docDetail.getDateValue() != null && docDetail.getToDateValue() == null) { //only first value entered
                    //sqlStat.append(" (DI.INDEX_" + pos + " >= '" + DateField.dateToString(docDetail.getDateValue()) + "' ) ");
                    sqlStat.append(" (DI.INDEX_" + pos + " >= '" + TextUtility.formatTimestampToIndex(docDetail.getDateValue()) + "' ) ");
                  } else if (docDetail.getDateValue() == null && docDetail.getToDateValue() != null) { //only 2nd value entered
                    //sqlStat.append(" (DI.INDEX_" + pos + " <= '" + DateField.dateToString(docDetail.getToDateValue()) + "' ) ");
                    sqlStat.append(" (DI.INDEX_" + pos + " <= '" + TextUtility.formatTimestampToIndex(docDetail.getToDateValue()) + "' ) ");
                  }
                }
                //sqlStat.append(" ) )  ");
                sqlStat.append(" ) ");
              } //end if
            } //end if after for
          } //end for
          sqlStat.append(" )  ");
          repe++;
        }
        
        //if (DmsOperationConstant.ATTR_NEST_FILTER_OPERATION.equals(docSearchForm.getOpMode()) ){
        if (!Utility.isEmpty(outerCriteria)) {
          outerCriteria = outerCriteria + " AND " + sqlStat.substring(startPos, sqlStat.length());
        } else {
          outerCriteria = sqlStat.substring(startPos, sqlStat.length());
        }
        //}
        
        //Add By Jim Zhou       2007/05/09      EIP-2338
        if ("(".equals(sqlStat.substring(sqlStat.toString().trim().length()-1,sqlStat.toString().trim().length()))){
          sqlStat.delete(sqlStat.lastIndexOf("AND"),sqlStat.length());
        } else {
          sqlStat.append(" ) ");
        }
        /*
        if ("AND ( ) ".equals(sqlStat.substring(sqlStat.length()-8))){
          sqlStat.delete(sqlStat.length()-8,sqlStat.length());
        }
        */
        //Add End
        
        if (rootIDs.size() > 0) {
          sqlStat.append(" AND ( ");
          for (int i = 0; i < rootIDs.size(); i++) {
            sqlStat.append(" D.ROOT_ID = ? ");
            if (i + 1 < rootIDs.size()) {
              sqlStat.append(" OR ");
            }
          }
          sqlStat.append(" )  ");
        } else {
          sqlStat.append(" AND D.ROOT_ID = ?   ");
        }
        
        //Apend the prv outer search criteria
        if (DmsOperationConstant.ATTR_NEST_FILTER_OPERATION.equals(docSearchForm.getOpMode()) &&
            !Utility.isEmpty(docSearchForm.getOuterCriteria())) {
          sqlStat.append(" AND (  " + docSearchForm.getOuterCriteria() + " ) ");
        } else if (DmsOperationConstant.ATTR_EXPORT_OPERATION.equals(docSearchForm.getOpMode()) ||
            DmsOperationConstant.ATTR_COMBINE_TIFF_OPERATION.equals(docSearchForm.getOpMode())) {
          if (DmsOperationConstant.ATTR_NEST_FILTER_OPERATION.equals(docSearchForm.getPrvOpMode()) &&
              !Utility.isEmpty(docSearchForm.getOuterCriteria())) {
            sqlStat.append(" AND (  " + docSearchForm.getOuterCriteria() + " ) ");
          }
        }
        
        
        sqlStat.append("AND ((D.EFFECTIVE_START_DATE IS NULL OR D.EFFECTIVE_START_DATE <= ?) OR D.OWNER_ID=?) ");
        if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
          sqlStat.append("       AND ((D.EFFECTIVE_END_DATE IS NULL OR D.EFFECTIVE_END_DATE > ?) ");
          sqlStat.append("       OR D.OWNER_ID = ?) ");
        }
//      sqlStat.append("  D.DOCUMENT_TYPE = 'D' AND D.RECORD_STATUS = ? ORDER BY D.ROOT_ID,D.ID");
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        sqlStat.append("ORDER BY D.DOCUMENT_TYPE DESC  ");
        
        if (docSearchForm.isSortable()) {
          
          String sortAttribute = docSearchForm.getSortAttribute();
          if (sortAttribute.indexOf(".") < 0) {
            sortAttribute = "D." + sortAttribute;
          }
          
          sqlStat.append(", " + sortAttribute + " " + searchForm.getSortOrder() + " ");
        }
        
        int i = 0;
        
        // Get total number of record return.
        StringBuffer sbResult = new StringBuffer("SELECT COUNT(DISTINCT(D.ID)) FROM ");
        int idx = sqlStat.indexOf("FROM ");
        sbResult.append(sqlStat.substring(idx + 5));
        if (sbResult.indexOf("ORDER BY") >= 0) {
          sbResult = new StringBuffer(sbResult.substring(0, sbResult.indexOf("ORDER BY") - 1));
        }
        log.info("COUNT SQL: " + sbResult);
        sqlStatCnt = sbResult;
        preStatCnt = dbConn.prepareStatement(sqlStatCnt.toString());
        
        String tmp1Cnt[] = null;
        this.setPrepareStatement(preStatCnt, ++i, GlobalConstant.RECORD_STATUS_ACTIVE);
        
        if (!Utility.isEmpty(docSearchForm.getDocumentName())) {
          
          List fieldList = (List) mFieldMap.get("DOCUMENT_NAME");
          for (int j = 0; j < fieldList.size(); j++) {
            log.debug("(String) fieldList.get(j) = " + fieldList);
            setPrepareStatement(preStatCnt, ++i, (String) fieldList.get(j));
          }
        }
        
        if (!Utility.isEmpty(docSearchForm.getDocumentType())) {
          List fieldList = (List) mFieldMap.get("DOCUMENT_TYPE");
          for (int j = 0; j < fieldList.size(); j++) {
            setPrepareStatement(preStatCnt, ++i, (String) fieldList.get(j));
          }
        }
        
        if (!Utility.isEmpty(docSearchForm.getSearchPriority())) {
          List fieldList = (List) mFieldMap.get("PRIORITY");
          for (int j = 0; j < fieldList.size(); j++) {
            setPrepareStatement(preStatCnt, ++i, (String) fieldList.get(j));
          }
        }        
        
        if (!Utility.isEmpty(docSearchForm.getReferenceNo())) {
          List fieldList = (List) mFieldMap.get("REFERENCE_NO");
          for (int j = 0; j < fieldList.size(); j++) {
            setPrepareStatement(preStatCnt, ++i, (String) fieldList.get(j));
          }
        }
        
        if (!Utility.isEmpty(docSearchForm.getDescription())) {
          List fieldList = (List) mFieldMap.get("DESCRIPTION");
          for (int j = 0; j < fieldList.size(); j++) {
            setPrepareStatement(preStatCnt, ++i, (String) fieldList.get(j));
          }
        }
        
        if (!Utility.isEmpty(docSearchForm.getCreatorID())) {
          List fieldList = (List) mFieldMap.get("CREATOR_ID");
          for (int j = 0; j < fieldList.size(); j++) {
            setPrepareStatement(preStatCnt, ++i, (String) fieldList.get(j));
          }
        }
        
        //iterate userDef1 to userDef10 using reflection
        for(int udfIdx = 1 ; udfIdx<=totalFieldCount ; udfIdx++){
          Class cls = Class.forName(ListDmsDocumentForm.class.getName());
          Method userDefMethod = cls.getMethod("getUserDef"+udfIdx,null);
          String userDefFrom = (String)userDefMethod.invoke(docSearchForm, null);
          Method userDefToMethod = cls.getMethod("getUserDef"+udfIdx+"To",null);
          String userDefTo = (String)userDefToMethod.invoke(docSearchForm, null);
          Method userDefDataTypeMethod = cls.getMethod("getUserDef"+udfIdx+"DataType",null);
          String userDefDataType = (String)userDefDataTypeMethod.invoke(docSearchForm, null);
          
          
          if ( (!Utility.isEmpty(userDefFrom)) || (!Utility.isEmpty(userDefTo))) {
            if (!DmsDefaultProfileSetting.FIELD_TYPE_DATE.equals(userDefDataType)) {
              List fieldList = (List) mFieldMap.get("USER_DEF_"+udfIdx);
              for (int j = 0; j < fieldList.size(); j++) {
                setPrepareStatement(preStatCnt, ++i, (String) fieldList.get(j));
              }              
            }            
          }
        }
        
        
        
        if (!Utility.isEmpty(docSearchForm.getUserDefinedFieldID())) {
          for (int j = 0; j < docDetailList.size(); j++) {
            DmsDocumentDetail docDetail = (DmsDocumentDetail) docDetailList.get(j);
            
            List fieldList = (List) mFieldMap.get("UDF_DETAIL_" + docDetail.getUserDefinedFieldDetailID() + "_FIELDVALUE");
            if (!Utility.isEmpty(fieldList)) {
              for (int k = 0; k < fieldList.size(); k++) {
                setPrepareStatement(preStatCnt, ++i, (String) fieldList.get(k));
              }
            }
          }
        }
        
        if (rootIDs.size() > 0) {
          for (int j = 0; j < rootIDs.size(); j++) {
            Integer rootID = TextUtility.parseIntegerObj( (String) rootIDs.get(j));
            log.debug("rooid = " + rootID);
            setPrepareStatement(preStatCnt, ++i, rootID);
          }
        } else {
          setPrepareStatement(preStatCnt, ++i, docSearchForm.getRootID());
          log.debug("rooid = " + docSearchForm.getRootID());
        }
        
        //Used for nest filtering
        String[] oldCriteriaValue = docSearchForm.getOuterCriteriaValue();
        if (DmsOperationConstant.ATTR_NEST_FILTER_OPERATION.equals(
            docSearchForm.getOpMode()) && oldCriteriaValue != null) {
          log.debug("        ....oldCriteriaValue = " + oldCriteriaValue.length);
          for (int o = 0; o < oldCriteriaValue.length; o++) {
            String tmpValue = oldCriteriaValue[o];
            if (!Utility.isEmpty(tmpValue) && !"null".equals(tmpValue)) {
              setPrepareStatement(preStatCnt, ++i, tmpValue);
            }
          }
          
        } else if (DmsOperationConstant.ATTR_EXPORT_OPERATION.equals(docSearchForm.getOpMode()) ||
            DmsOperationConstant.ATTR_COMBINE_TIFF_OPERATION.equals(docSearchForm.getOpMode())) {
          if (DmsOperationConstant.ATTR_NEST_FILTER_OPERATION.equals(docSearchForm.getPrvOpMode()) &&
              oldCriteriaValue != null) {
            log.debug("        ....oldCriteriaValue = " + oldCriteriaValue.length);
            for (int o = 0; o < oldCriteriaValue.length; o++) {
              String tmpValue = oldCriteriaValue[o];
              if (!Utility.isEmpty(tmpValue) && !"null".equals(tmpValue)) {
                setPrepareStatement(preStatCnt, ++i, tmpValue);
              }
            }
          }
        }
        
        this.setPrepareStatement(preStatCnt, ++i, currTime);
        this.setPrepareStatement(preStatCnt, ++i, this.sessionContainer.getUserRecordID());
        if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
          this.setPrepareStatement(preStatCnt, ++i, oneDayBeforeCurrTime);
          this.setPrepareStatement(preStatCnt, ++i, this.sessionContainer.getUserRecordID());
        }
        
        rsCnt = preStatCnt.executeQuery();
        if (rsCnt.next()) {
          totalNumOfRecord = rsCnt.getInt(1);
        }
        log.debug("totalNumOfRecord =  " + totalNumOfRecord);
        try {
          rsCnt.close();
        } catch (Exception ignore) {} finally {
          rsCnt = null;
        }
        try {
          preStatCnt.close();
        } catch (Exception ignore) {} finally {
          preStatCnt = null;
        }
        log.debug("search result option = " + docSearchForm.getSearchResultOpt() + " = " + DmsOperationConstant.SEARCH_RESULT_ALL);
        if (!DmsOperationConstant.SEARCH_RESULT_ALL.equals(docSearchForm.getSearchResultOpt())) {
          // Retrieve the result in row basis.
          sqlStat = this.getSelectListSQL(sqlStat, startOffset, pageSize);
        } else {
          log.info("SELECT SQL: " + sqlStat);
        }
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        
        String tmp1[] = null;
        i = 0;
        List outerCriteriaValue = new ArrayList();
        
        setPrepareStatement(preStat, ++i, GlobalConstant.RECORD_STATUS_ACTIVE);
        
        if (!Utility.isEmpty(docSearchForm.getDocumentName())) {
          List fieldList = (List) mFieldMap.get("DOCUMENT_NAME");
          for (int j = 0; j < fieldList.size(); j++) {
            setPrepareStatement(preStat, ++i, (String) fieldList.get(j));
            outerCriteriaValue.add( fieldList.get(j));
          }
        } else {
          outerCriteriaValue.add("null");
        }
        
        if (!Utility.isEmpty(docSearchForm.getDocumentType())) {
          List fieldList = (List) mFieldMap.get("DOCUMENT_TYPE");
          for (int j = 0; j < fieldList.size(); j++) {
            setPrepareStatement(preStat, ++i, (String) fieldList.get(j));
            outerCriteriaValue.add( fieldList.get(j));
          }
        } else {
          outerCriteriaValue.add("null");
        }
        
        if (!Utility.isEmpty(docSearchForm.getSearchPriority())) {
          List fieldList = (List) mFieldMap.get("PRIORITY");
          for (int j = 0; j < fieldList.size(); j++) {
            setPrepareStatement(preStat, ++i, (String) fieldList.get(j));
            outerCriteriaValue.add( fieldList.get(j));
          }
        } else {
          outerCriteriaValue.add("null");
        }
        
        if (!Utility.isEmpty(docSearchForm.getReferenceNo())) {
          List fieldList = (List) mFieldMap.get("REFERENCE_NO");
          for (int j = 0; j < fieldList.size(); j++) {
            setPrepareStatement(preStat, ++i, (String) fieldList.get(j));
            outerCriteriaValue.add( fieldList.get(j));
          }
        } else {
          outerCriteriaValue.add("null");
        }
        
        if (!Utility.isEmpty(docSearchForm.getDescription())) {
          List fieldList = (List) mFieldMap.get("DESCRIPTION");
          for (int j = 0; j < fieldList.size(); j++) {
            setPrepareStatement(preStat, ++i, (String) fieldList.get(j));
            outerCriteriaValue.add( fieldList.get(j));
          }
        } else {
          outerCriteriaValue.add("null");
        }
        
        if (!Utility.isEmpty(docSearchForm.getCreatorID())) {
          List fieldList = (List) mFieldMap.get("CREATOR_ID");
          for (int j = 0; j < fieldList.size(); j++) {
            setPrepareStatement(preStat, ++i, (String) fieldList.get(j));
            outerCriteriaValue.add( fieldList.get(j));
          }
        } else {
          outerCriteriaValue.add("null");
        }
        
        //iterate userDef1 to userDef10 using reflection
        for(int udfIdx = 1 ; udfIdx<=totalFieldCount ; udfIdx++){
          Class cls = Class.forName(ListDmsDocumentForm.class.getName());
          Method userDefMethod = cls.getMethod("getUserDef"+udfIdx,null);
          String userDefFrom = (String)userDefMethod.invoke(docSearchForm, null);
          Method userDefToMethod = cls.getMethod("getUserDef"+udfIdx+"To",null);
          String userDefTo = (String)userDefToMethod.invoke(docSearchForm, null);
          Method userDefDataTypeMethod = cls.getMethod("getUserDef"+udfIdx+"DataType",null);
          String userDefDataType = (String)userDefDataTypeMethod.invoke(docSearchForm, null);
          
          
          if ( (!Utility.isEmpty(userDefFrom)) || (!Utility.isEmpty(userDefTo))) {
            if (!DmsDefaultProfileSetting.FIELD_TYPE_DATE.equals(userDefDataType)) {
              List fieldList = (List) mFieldMap.get("USER_DEF_"+udfIdx);
              for (int j = 0; j < fieldList.size(); j++) {
                setPrepareStatement(preStat, ++i, (String) fieldList.get(j));
                outerCriteriaValue.add( fieldList.get(j));
              }           
            } else {
              outerCriteriaValue.add("null");
            }
          } else {
            outerCriteriaValue.add("null");
          }
        }
        
        
        if (!Utility.isEmpty(docSearchForm.getUserDefinedFieldID())) {
          for (int j = 0; j < docDetailList.size(); j++) {
            DmsDocumentDetail docDetail = (DmsDocumentDetail) docDetailList.get(j);
            List fieldList = (List) mFieldMap.get("UDF_DETAIL_" + docDetail.getUserDefinedFieldDetailID() + "_FIELDVALUE");
            if (!Utility.isEmpty(fieldList)) {
              for (int k = 0; k < fieldList.size(); k++) {
                
                setPrepareStatement(preStat, ++i, (String) fieldList.get(k));
                outerCriteriaValue.add( fieldList.get(k));
                log.debug("the field is:" + (String) fieldList.get(k));
              }
            } else {
              outerCriteriaValue.add("null");
            }
            
          }
        }
        
        if (rootIDs.size() > 0) {
          for (int j = 0; j < rootIDs.size(); j++) {
            Integer rootID = TextUtility.parseIntegerObj( (String) rootIDs.get(
                j));
            setPrepareStatement(preStat, ++i, rootID);
          }
        } else {
          setPrepareStatement(preStat, ++i, docSearchForm.getRootID());
        }
        
        //Used for nest filtering
        //String[] oldCriteriaValue = docSearchForm.getOuterCriteriaValue();
        if (DmsOperationConstant.ATTR_NEST_FILTER_OPERATION.equals(
            docSearchForm.getOpMode()) && oldCriteriaValue != null) {
            for (int o = 0; o < oldCriteriaValue.length; o++) {
              String tmpValue = oldCriteriaValue[o];
              if (!Utility.isEmpty(tmpValue) && !"null".equals(tmpValue)) {
                setPrepareStatement(preStat, ++i, oldCriteriaValue[o]);
              }
            }
        } else if (DmsOperationConstant.ATTR_EXPORT_OPERATION.equals(
            docSearchForm.getOpMode()) ||
            DmsOperationConstant.
            ATTR_COMBINE_TIFF_OPERATION.equals(docSearchForm.getOpMode())) {
          if (DmsOperationConstant.ATTR_NEST_FILTER_OPERATION.equals(
              docSearchForm.getPrvOpMode()) &&
              oldCriteriaValue != null) {
            for (int o = 0; o < oldCriteriaValue.length; o++) {
              String tmpValue = oldCriteriaValue[o];
              if (!Utility.isEmpty(tmpValue) && !"null".equals(tmpValue)) {
                setPrepareStatement(preStat, ++i, oldCriteriaValue[o]);
              }
            }
            
          }
        }
        
        setPrepareStatement(preStat, ++i, currTime);
        setPrepareStatement(preStat, ++i, this.sessionContainer.getUserRecordID());
        if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
          setPrepareStatement(preStat, ++i, oneDayBeforeCurrTime);
          setPrepareStatement(preStat, ++i, this.sessionContainer.getUserRecordID());
        }
        
        rs = preStat.executeQuery();
        if (!DmsOperationConstant.SEARCH_RESULT_ALL.equals(docSearchForm.getSearchResultOpt())) {
          // Retrieve the result in row basis.
          this.positionCursor(rs, startOffset, pageSize);
        }      
        int j = 0;
        
        while (rs.next() && rowLoopCnt < pageSize) {
          DmsDocument tmpDmsDocument = new DmsDocument();
          tmpDmsDocument.setID(getResultSetInteger(rs, "ID"));
          tmpDmsDocument.setDocumentName(getResultSetString(rs, "DOCUMENT_NAME"));
          tmpDmsDocument.setDocumentType(getResultSetString(rs, "DOCUMENT_TYPE"));
          tmpDmsDocument.setParentID(getResultSetInteger(rs, "PARENT_ID"));
          tmpDmsDocument.setRootID(getResultSetInteger(rs, "ROOT_ID"));
          tmpDmsDocument.setPriority(getResultSetString(rs, "PRIORITY"));
          tmpDmsDocument.setCreateType(getResultSetString(rs, "CREATE_TYPE"));
          tmpDmsDocument.setEffectiveStartDate(getResultSetTimestamp(rs, "EFFECTIVE_START_DATE"));
          tmpDmsDocument.setEffectiveEndDate(getResultSetTimestamp(rs, "EFFECTIVE_END_DATE"));
          tmpDmsDocument.setReminderAmount(getResultSetInteger(rs, "REMINDER_AMOUNT"));
          tmpDmsDocument.setReminderType(getResultSetString(rs, "REMINDER_TYPE"));
          tmpDmsDocument.setNotificationWay(getResultSetStringAry(rs, "NOTIFICATION_WAY", ";"));
          tmpDmsDocument.setOwnerID(getResultSetInteger(rs, "OWNER_ID"));
          tmpDmsDocument.setReferenceNo(getResultSetString(rs, "REFERENCE_NO"));
          tmpDmsDocument.setDescription(getResultSetString(rs, "DESCRIPTION"));
          tmpDmsDocument.setItemSize(getResultSetInteger(rs, "ITEM_SIZE"));
          tmpDmsDocument.setItemStatus(getResultSetString(rs, "ITEM_STATUS"));
          tmpDmsDocument.setCheckoutID(getResultSetInteger(rs, "CHECKOUT_ID"));
          tmpDmsDocument.setAlertEditID(getResultSetInteger(rs, "ALERT_EDIT_ID"));
          tmpDmsDocument.setAlertInviteID(getResultSetInteger(rs, "ALERT_INVITE_ID"));
          tmpDmsDocument.setExtRef(getResultSetString(rs, "EXT_REF"));           
          tmpDmsDocument.setUserDef1(getResultSetString(rs, "USER_DEF_1"));
          tmpDmsDocument.setUserDef2(getResultSetString(rs, "USER_DEF_2"));
          tmpDmsDocument.setUserDef3(getResultSetString(rs, "USER_DEF_3"));
          tmpDmsDocument.setUserDef4(getResultSetString(rs, "USER_DEF_4"));
          tmpDmsDocument.setUserDef5(getResultSetString(rs, "USER_DEF_5"));
          tmpDmsDocument.setUserDef6(getResultSetString(rs, "USER_DEF_6"));
          tmpDmsDocument.setUserDef7(getResultSetString(rs, "USER_DEF_7"));
          tmpDmsDocument.setUserDef8(getResultSetString(rs, "USER_DEF_8"));
          tmpDmsDocument.setUserDef9(getResultSetString(rs, "USER_DEF_9"));
          tmpDmsDocument.setUserDef10(getResultSetString(rs, "USER_DEF_10"));
          tmpDmsDocument.setRecordStatus(getResultSetString(rs, "RECORD_STATUS"));
          tmpDmsDocument.setUpdateCount(getResultSetInteger(rs, "UPDATE_COUNT"));
          tmpDmsDocument.setCreatorID(getResultSetInteger(rs, "CREATOR_ID"));
          tmpDmsDocument.setCreateDate(getResultSetTimestamp(rs, "CREATE_DATE"));
          tmpDmsDocument.setUpdaterID(getResultSetInteger(rs, "UPDATER_ID"));
          tmpDmsDocument.setUpdateDate(getResultSetTimestamp(rs, "UPDATE_DATE"));
          if (!Utility.isEmpty(docSearchForm.getUserDefinedFieldID())) {
            tmpDmsDocument.setUserDefinedFieldID(getResultSetInteger(rs, "USER_DEFINED_FIELD_ID"));
          }
          
          tmpDmsDocument.setCreatorName(UserInfoFactory.getUserFullName(tmpDmsDocument.getCreatorID()));
          tmpDmsDocument.setUpdaterName(UserInfoFactory.getUserFullName(tmpDmsDocument.getUpdaterID()));
          tmpDmsDocument.setRecordCount(totalNumOfRecord);
          tmpDmsDocument.setRowNum(startOffset++);
          
          if (j == 0) { //set the value temp for later retrieval
            tmpDmsDocument.setOuterCriteria(outerCriteria);
            int oldSize = 0;
            if (DmsOperationConstant.ATTR_NEST_FILTER_OPERATION.equals(
                docSearchForm.getOpMode()) && oldCriteriaValue != null) {
              oldSize = oldCriteriaValue.length;
            } else if (DmsOperationConstant.ATTR_EXPORT_OPERATION.equals(
                docSearchForm.getOpMode()) || DmsOperationConstant.ATTR_COMBINE_TIFF_OPERATION.equals(docSearchForm.getOpMode())) {
              if (DmsOperationConstant.ATTR_NEST_FILTER_OPERATION.equals(
                  docSearchForm.getOpMode()) && oldCriteriaValue != null) {
                oldSize = oldCriteriaValue.length;
              }
            }
            
            int outerSize = outerCriteriaValue == null ? 0 :
              outerCriteriaValue.size();
            String[] newCriteriaValue = new String[oldSize + outerSize];
            int newCriteriaNum = 0;
            if (DmsOperationConstant.ATTR_NEST_FILTER_OPERATION.equals(
                docSearchForm.getOpMode()) && oldCriteriaValue != null) {
              for (int k = 0; k < oldCriteriaValue.length; k++) {
                newCriteriaValue[newCriteriaNum] = oldCriteriaValue[k];
                newCriteriaNum++;
              }
            } else if (DmsOperationConstant.ATTR_EXPORT_OPERATION.equals(
                docSearchForm.getOpMode()) || DmsOperationConstant.ATTR_COMBINE_TIFF_OPERATION.equals(docSearchForm.getOpMode())) {
              if (DmsOperationConstant.ATTR_NEST_FILTER_OPERATION.equals(
                  docSearchForm.getOpMode()) && oldCriteriaValue != null) {
                for (int k = 0; k < oldCriteriaValue.length; k++) {
                  newCriteriaValue[newCriteriaNum] = oldCriteriaValue[k];
                  newCriteriaNum++;
                }
              }
            }
            
            for (int k = 0; k < outerCriteriaValue.size(); k++) {
              newCriteriaValue[newCriteriaNum] = (String) outerCriteriaValue.get(k);
              newCriteriaNum++;
            }
            tmpDmsDocument.setOuterCriteriaValue(newCriteriaValue);
            j++;
          }
          
          if (!DmsOperationConstant.SEARCH_RESULT_ALL.equals(docSearchForm.getSearchResultOpt())) {
            ++rowLoopCnt;
          }
          
          result.add(tmpDmsDocument);
          
          
        }
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
        try {
          rsCnt.close();
        } catch (Exception ignore) {} finally {
          rsCnt = null;
        }
        try {
          preStatCnt.close();
        } catch (Exception ignore) {} finally {
          preStatCnt = null;
        }
      }
    }
  }
  
  
  /**
   * Gets the list of the document(s) that match the search criteria specified in the list of ListDmsDocumentForm objects 
   * and under root specified the list of rootIDs.
   * <P>
   * This method used for the Bulk search operations to get the multi search objects
   * </P>
   * <P>
   * If you pass in a list of ListDmsDocumentForm
   * object(s), each of the ListDmsDocumentForm properties if contains value will used as the search criteria.
   * The ListDmsDocumentForm objects search criteria forms a "OR" case operation i.e. it will combine the search criteria as: 
   * The first search ListDmsDocumentForm object search criteria OR The second list ListDmsDocumentForm object search criteria
   * </P>
   * <table border=1 cellspacing=1 cellpadding=1>
   * <tr><th>Property</th><th>Description</th><th>Possible values</th></tr>
   * <tr><td>document name</td><td>document name</td><td>any string value</td>/tr>
   * <tr><td>EffectiveStartDate</td><td>effective start date</td><td>date in format {@link com.dcivision.framework#DB_DATETIME_FORMAT} </td></tr>
   * <tr><td>EffectiveEndDate</td><td>effective end date<td><td>date in format {@link com.dcivision.framework#DB_DATETIME_FORMAT} </td></tr>
   * <tr><td>CreateDate</td><td>Create Date</td><td>date in format {@link com.dcivision.framework#DB_DATETIME_FORMAT} </td></tr>
   * <tr><td>UpdateDate</td><td>Update Date</td><td>date in format {@link com.dcivision.framework#DB_DATETIME_FORMAT} </td></tr>
   * <tr><td>DocumentType</td><td>document type</td><td>{@link com.dcivision.dms.bean.DmsDocument#DOCUMENT_TYPE},
   *                                                    {@link com.dcivision.dms.bean.DmsDocument#COMPOUND_DOC_TYPE},
   *                                                    {@link com.dcivision.dms.bean.DmsDocument#DOCUMENT_LINK},
   *                                                    {@link com.dcivision.dms.bean.DmsDocument#FOLDER_TYPE} 
   *                                                </td></tr>
   * <tr><td>ReferenceNo</td><td>Document reference no</td><td>any string value</td></tr>
   * <tr><td>Priority</td><td>Document Priority</td><td>{@link com.dcivision.framework.GlobalConstant#PRIORITY_HIGH},{@link com.dcivision.framework.GlobalConstant#PRIORITY_LOW},{@link com.dcivision.framework.GlobalConstant#PRIORITY_MEDIUM}</td></tr>
   * <tr><td>Description</td><td>Document description</td><td>any string values</td></tr>
   * <tr><td>UserDef1 (1-10)</td><td>User defined value 1-10 (default profile values)</td><td>any string values</td></tr>
   * <tr><td>UserDef1To(1-10)</td><td>uppper range limit for numeric or date type of user defined values</td><td>any string values</td></tr>
   * <tr><td>UserDefinedFieldID</td><td>document profile</td><td>{@link com.dcivision.framework.bean.SysUserDefinedIndex#getID()}</td></tr>
   * <tr><td>DocumentDetails</td><td>List of Document Detail object</td><td>&nbsp;</td></tr>
   * <tr><td colspan='3'>the document detail object(user profile field value) 
   *                    <br>properties set for searching as follow:</td></tr>
   * <tr><td>FieldValue</td><td>String type document detail 
   *                           <br>{@link com.dcivision.framework.bean.SysUserDefinedIndexDetail#STRING_FIELD}</td><td>any string values</td></tr>
   * <tr><td>NumericValue</td><td>Numeric type document detail
   *                             <br>{@link com.dcivision.framework.bean.SysUserDefinedIndex#NUMBER_FIELD}</td><td>any string values</td></tr>
   *<tr><td>ToNumericValue</td><td>upper range limit Numeric type document detail</td><td>any string values in numeric format</td></tr>
   *<tr><td>DateValue</td><td>Date type document detail
   *                             <br>{@link com.dcivision.framework.bean.SysUserDefinedIndex#DATE_FIELD}</td><td>any string values</td></tr>
   *<tr><td>ToDateValue</td><td>upper range limit Date type document detail</td><td>any string values in Date format {@link com.dcivision.framework#DB_DATETIME_FORMAT}</td></tr>
   * </table>
   * 
   * <PRE>
   * 
   * Each of the search properties contains 2 search options i.e. for Description field
   *    options                   Usage
   * 1. DescriptionExactMatch -   Exact match the search criteria   
   * 2. DescriptionOption     -   Specifiy the Operand with other search fields(And/OR)
   * 
   * Special search function also support in search
   * 1. relational search - any string type searching, if it is chinese char(s), both the simplified chinese or traditional chinese char also be searched
   *                        if SystemParameterConstant.DMS_RELATIONAL_WORD_ENABLE set to true in SYS_PARAMETER table, 
   *                        the user defined relational word also be searched.
   * 
   * 2. range search - special char (>=, >, AND, OR, NOT) in the search field, extra search criteria is added. e.g.
   *                   search document name as ">= 1000001.tif", the document name greater than or equal to 1000001.tif will be searched.
   * 
   * </PRE>
   * @param searchForm the ListDmsDocumentForm object for paging and display setting
   * @param rootIDs the list of the root ID to limit the searched document under the given root
   * @param searchFormList List of ListDmsDocumentForm object(s) which are the search criteria
   * @return List the document(s) matched the search criteria
   * @throws ApplicationException
   
   * <pre>
   * 
   *            ApplicationException with the following message codes will be thrown
   *            ErrorConstant.ErrorConstant.DB_GENERAL_ERROR - General caught SQLException
   *            ErrorConstant.DB_SELECT_ERROR - All kind of caught Exception
   *  
   * </pre>
   * 
   * 
   */
  
  public synchronized List getListByImportSearchObjectList(AbstractSearchForm searchForm, List rootIDs, List searchFormList) throws ApplicationException {
    
    PreparedStatement preStat = null;
    PreparedStatement preStatCnt = null;
    ResultSet rs = null;
    ResultSet rsCnt = null;
    StringBuffer sqlStat = new StringBuffer();
    StringBuffer sqlStatCnt = new StringBuffer();
    List result = new ArrayList();
    int totalNumOfRecord = 0;
    int rowLoopCnt = 0;
    int startOffset = TextUtility.parseInteger(searchForm.getCurStartRowNo());
    int pageSize = TextUtility.parseInteger(searchForm.getPageOffset());
    int udfDetailCount = 0;
    Map udfFieldAllMap = new HashMap();
    ListDmsDocumentForm docSearchForm = (ListDmsDocumentForm) searchForm;
    List docDetailList = new ArrayList();
    DmsDocumentDetail docDetail = new DmsDocumentDetail();
    HashMap mFieldMap = new HashMap();
    int tmpCounter = 0;
    //relational word is false or true
    boolean isRelationWord = SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_RELATIONAL_WORD_ENABLE);
    DocumentRetrievalManager docRetrievalManager = new DocumentRetrievalManager(sessionContainer, dbConn);
    Timestamp currTime = Utility.getCurrentTimestamp();
    Timestamp oneDayBeforeCurrTime = Utility.addDay(currTime, -1);
    DmsRelationalWordDAObject dmsRelationalWordDaobject = new DmsRelationalWordDAObject(sessionContainer, dbConn);
    DmsRelationalWord dmsRelationalWord = new DmsRelationalWord();
    synchronized (dbConn) {
      try {
        ListDmsDocumentForm searchObject = (ListDmsDocumentForm) searchFormList.get(0);
        
        //SQL
        sqlStat.append("SELECT DISTINCT(D.ID), ");
        sqlStat.append("D.DOCUMENT_NAME, D.DOCUMENT_TYPE, D.PARENT_ID, D.ROOT_ID, D.PRIORITY, D.CREATE_TYPE, D.EFFECTIVE_START_DATE, D.EFFECTIVE_END_DATE, D.REMINDER_AMOUNT, D.REMINDER_TYPE, D.NOTIFICATION_WAY, D.OWNER_ID, D.REFERENCE_NO, D.DESCRIPTION, D.ITEM_SIZE, D.ITEM_STATUS, D.CHECKOUT_ID, D.ALERT_EDIT_ID, D.ALERT_INVITE_ID, D.EXT_REF,D.USER_DEF_1, D.USER_DEF_2, D.USER_DEF_3, D.USER_DEF_4, D.USER_DEF_5, D.USER_DEF_6, D.USER_DEF_7, D.USER_DEF_8, D.USER_DEF_9, D.USER_DEF_10, D.RECORD_STATUS, D.UPDATE_COUNT, D.CREATOR_ID, D.CREATE_DATE, D.UPDATER_ID, D.UPDATE_DATE ");
        
        if (searchObject.getUserDefinedFieldID() != null) {
          sqlStat.append(", DI.USER_DEFINED_FIELD_ID ");
        }
        
        /* sqlStat.append("FROM DMS_DOCUMENT D ");
         if (searchObject.getUserDefinedFieldID() != null) {
         sqlStat.append(", DMS_DOCUMENT_DETAIL DD   ");
         }*/
        
        sqlStat.append("FROM  ");
        //   table1 LEFT JOIN table2 ON table1.id=table2.id
        if (searchObject.getUserDefinedFieldID() != null) {
          
          sqlStat.append(" DMS_DOCUMENT D LEFT JOIN DMS_DOCUMENT_INDEX DI ON D.ID=DI.DOCUMENT_ID ");
        } else {
          
          sqlStat.append(" DMS_DOCUMENT D ");
        }
        
        sqlStat.append("WHERE ");
        
        //to ensure no root folder is selected
        sqlStat.append(" D.PARENT_ID <> 0 AND ");
        
        // TIF_ANNOTATION_TYPE / ORIGINSLITY_EMAIL_TYPE should no display in result list(EIP-1296 lee 07/01/18)
        sqlStat.append(" D.DOCUMENT_TYPE <> '"+DmsDocument.TIF_ANNOTATION_TYPE+"' AND ");
        sqlStat.append(" D.DOCUMENT_TYPE <> '"+DmsDocument.ORIGINSLITY_EMAIL_TYPE+"' AND ");
        
        sqlStat.append(" D.RECORD_STATUS = '" + GlobalConstant.RECORD_STATUS_ACTIVE + "' AND   ");
        if (!Utility.isEmpty(searchFormList)) {
          ListDmsDocumentForm tmpSearchObject = (ListDmsDocumentForm) searchFormList.get(0);
          docDetailList = tmpSearchObject.getDocumentDetails();
          if (!Utility.isEmpty(docDetailList)) {
            docDetail = (DmsDocumentDetail) docDetailList.get(0);
            //sqlStat.append("  DD.USER_DEFINED_FIELD_ID = " + docDetail.getUserDefinedFieldID().toString() + " AND ");
            sqlStat.append("  DI.USER_DEFINED_FIELD_ID = " + docDetail.getUserDefinedFieldID().toString() + " AND ");
          }
        }
        sqlStat.append(" ( ");
        
        for (int k = 0; k < searchFormList.size(); k++) {
          searchObject = (ListDmsDocumentForm) searchFormList.get(k);
          if (k != 0) {
            sqlStat.append(" OR  ");
          } ;
            sqlStat.append(" (  ");
            
            int repe = 0;
            String tmp[] = null;
            
            if (rootIDs.size() > 0) {
              sqlStat.append("  ( ");
              for (int i = 0; i < rootIDs.size(); i++) {
                sqlStat.append(" D.ROOT_ID = ? ");
                if (i + 1 < rootIDs.size()) {
                  sqlStat.append(" OR ");
                }
              }
              sqlStat.append(" )  ");
            } else {
              sqlStat.append("  D.ROOT_ID = ?   ");
            }
            if (!Utility.isEmpty(searchObject.getDocumentName())) {
              log.debug("document name:" + searchObject.getDocumentName());
              sqlStat.append(" AND ");
              
              String sGetDocumentName=searchObject.getDocumentName();
              String sDocumentName=TextUtility.convert(searchObject.getDocumentName());//convert Big5 to GB or GB to Big5
              String nGetDocumentName=sGetDocumentName;
              if(!TextUtility.checkContainsOperandChar(searchObject.getDocumentName())){
                nGetDocumentName=sGetDocumentName+" OR "+sDocumentName;
                if(isRelationWord){//relatioanal word
                  List relationalDocumentNameList = dmsRelationalWordDaobject.getRelationalWordListByKeyWord(searchObject.getDocumentName());
                  for(int i=0;i<relationalDocumentNameList.size();i++){
                    dmsRelationalWord = (DmsRelationalWord)relationalDocumentNameList.get(i);
                    String relationDocumentName = dmsRelationalWord.getWord();
                    nGetDocumentName += " OR " + TextUtility.convert(relationDocumentName) + " OR " +relationDocumentName ;
                  }
                }
              }
              
              HashMap mResult = getCriteriaCombination("D.DOCUMENT_NAME", nGetDocumentName , searchObject.getDocumentNameExactMatch());
              sqlStat.append(mResult.get("SQL"));
              repe += TextUtility.parseInteger( (String) mResult.get("?"));
              mFieldMap.put("DOCUMENT_NAME_" + k, mResult.get("fieldResult"));
            }
            
            if (!Utility.isEmpty(searchObject.getEffectiveStartDate()) ||
                !Utility.isEmpty(searchObject.getEffectiveEndDate())) {
              sqlStat.append(" AND ");
              
              if (DataSourceFactory.getDatabaseType() == DataSourceFactory.DB_ORACLE) {
                if ( (!Utility.isEmpty(searchObject.getEffectiveStartDate())) &&
                    (!Utility.isEmpty(searchObject.getEffectiveEndDate()))) {
                  sqlStat.append(" (D.EFFECTIVE_START_DATE < TO_DATE('" + TextUtility.dbDateAdder(searchObject.getEffectiveEndDate(), 1) + "','"+"YYYY-MM-DD HH24:MI:SS" +"') AND D.EFFECTIVE_END_DATE > TO_DATE('" + searchObject.getEffectiveStartDate() +
                      "','"+"YYYY-MM-DD HH24:MI:SS"+"' )) ");
                } else if ( (!Utility.isEmpty(searchObject.getEffectiveStartDate())) && //only first value entered
                    (Utility.isEmpty(searchObject.getEffectiveEndDate()))) {
                  sqlStat.append(" (D.EFFECTIVE_START_DATE >= TO_DATE('" + searchObject.getEffectiveStartDate() + "','"+ "YYYY-MM-DD HH24:MI:SS"+"' )) ");
                } else if ( (Utility.isEmpty(searchObject.getEffectiveStartDate())) && //only 2nd value entered
                    (!Utility.isEmpty(searchObject.getEffectiveEndDate()))) {
                  sqlStat.append(" (D.EFFECTIVE_END_DATE < TO_DATE('" + TextUtility.dbDateAdder(searchObject.getEffectiveEndDate(), 1) + "','"+ "YYYY-MM-DD HH24:MI:SS" + "' )) ");
                }
              }else{
                if ( (!Utility.isEmpty(searchObject.getEffectiveStartDate())) &&
                    (!Utility.isEmpty(searchObject.getEffectiveEndDate()))) {
                  sqlStat.append(" (D.EFFECTIVE_START_DATE < '" + TextUtility.dbDateAdder(searchObject.getEffectiveEndDate(), 1) + "' AND D.EFFECTIVE_END_DATE > '" + searchObject.getEffectiveStartDate() +
                  "' ) ");
                } else if ( (!Utility.isEmpty(searchObject.getEffectiveStartDate())) && //only first value entered
                    (Utility.isEmpty(searchObject.getEffectiveEndDate()))) {
                  sqlStat.append(" (D.EFFECTIVE_START_DATE >= '" + searchObject.getEffectiveStartDate() + "' ) ");
                } else if ( (Utility.isEmpty(searchObject.getEffectiveStartDate())) && //only 2nd value entered
                    (!Utility.isEmpty(searchObject.getEffectiveEndDate()))) {
                  sqlStat.append(" (D.EFFECTIVE_END_DATE < '" + TextUtility.dbDateAdder(searchObject.getEffectiveEndDate(), 1) + "' ) ");
                }
                
                
              }
              
            }
            
            if (!Utility.isEmpty(searchObject.getReferenceNo())) {
              sqlStat.append(" AND ");
              HashMap mResult = getCriteriaCombination("D.REFERENCE_NO", searchObject.getReferenceNo(), searchObject.getReferenceNoExactMatch());
              sqlStat.append(mResult.get("SQL"));
              repe += TextUtility.parseInteger( (String) mResult.get("?"));
              mFieldMap.put("REFERENCE_NO_" + k, mResult.get("fieldResult"));
            }
            
            if (!Utility.isEmpty(searchObject.getDescription())) {
              sqlStat.append(" AND ");
              if (tmpCounter > 1) {
                sqlStat.append(" " + searchObject.getDescriptionOption() + " ");
              }
              
              String sDescription=TextUtility.convert(searchObject.getDescription());//convert big5 to gb or gb to big5
              String description=searchObject.getDescription();
              String nDescription=description ;
              if(!TextUtility.checkContainsOperandChar(searchObject.getDescription())){
                nDescription=sDescription + " OR " + description;
                if(isRelationWord){//relatioanal word
                  List relationalDescriptionList = dmsRelationalWordDaobject.getRelationalWordListByKeyWord(searchObject.getDescription());
                  for(int i=0;i<relationalDescriptionList.size();i++){
                    dmsRelationalWord = (DmsRelationalWord)relationalDescriptionList.get(i);
                    String relationDescription = dmsRelationalWord.getWord();
                    nDescription += " OR " + TextUtility.convert(relationDescription) + " OR " +relationDescription ;
                  }
                }
              }
              HashMap mResult = getCriteriaCombination("D.DESCRIPTION", nDescription, searchObject.getDescriptionExactMatch());
              sqlStat.append(mResult.get("SQL"));
              repe += TextUtility.parseInteger( (String) mResult.get("?"));
              mFieldMap.put("DESCRIPTION_" + k, mResult.get("fieldResult"));
              
            }
            
            
            //iterate userDef1 to userDef10 using reflection
            for(int udfIdx = 1 ; udfIdx<=10 ; udfIdx++){
              Class cls = Class.forName(ListDmsDocumentForm.class.getName());
              Method userDefMethod = cls.getMethod("getUserDef"+udfIdx,null);
              String userDefFrom = (String)userDefMethod.invoke(searchObject, null);
              Method userDefToMethod = cls.getMethod("getUserDef"+udfIdx+"To",null);
              String userDefTo = (String)userDefToMethod.invoke(searchObject, null);
              Method userDefOptionMethod = cls.getMethod("getUserDef"+udfIdx+"Option",null);
              String userDefOption = (String)userDefOptionMethod.invoke(searchObject, null);
              
              Method userDefDataTypeMethod = cls.getMethod("getUserDef"+udfIdx+"DataType",null);
              String userDefDataType = (String)userDefDataTypeMethod.invoke(searchObject, null);
              
              Method userDefExactMatchMethod = cls.getMethod("getUserDef"+udfIdx+"ExactMatch",null);
              
              boolean userDefExactMatch = ((Boolean)userDefExactMatchMethod.invoke(searchObject, null)).booleanValue();         
              if ( (!Utility.isEmpty(userDefFrom)) || (!Utility.isEmpty(userDefTo))) {
                sqlStat.append(" AND ");
                if (tmpCounter > 1) {
                  sqlStat.append(" " +userDefOption + " ");
                }
                
                if (DmsDefaultProfileSetting.FIELD_TYPE_DATE.equals(userDefDataType)) {
                  if ( (!Utility.isEmpty(userDefFrom)) && (!Utility.isEmpty(userDefTo))) {
                    sqlStat.append(" (D.USER_DEF_" + udfIdx + " >= '" + userDefFrom + "' AND D.USER_DEF_" + udfIdx + " <= '" + userDefTo + "' ) ");
                  }else{              
                    sqlStat.append("(");
                    if ( !Utility.isEmpty(userDefFrom) ) { //only first value entered               
                      sqlStat.append(" D.USER_DEF_" + udfIdx + " >= '" + userDefFrom + "' ");               
                    }else{ //only 2nd value entered
                      sqlStat.append(" D.USER_DEF_" + udfIdx + "  <= '" + userDefTo + "' ");
                    }
                    if (DataSourceFactory.getDatabaseType() == DataSourceFactory.DB_ORACLE) {              
                      sqlStat.append(" AND LENGTH(D.USER_DEF_" + udfIdx + ") > 0 ");              
                    }else{
                      sqlStat.append(" AND D.USER_DEF_" + udfIdx + " <> '' ");
                    }
                    sqlStat.append(")");
                  }
                } else {
                  String sUserDef=userDefFrom;
                  String getUserDef=TextUtility.convert(sUserDef);//convert big5 to gb or gb to big5
                  String sGetUserDef=sUserDef;
                  if(!TextUtility.checkContainsOperandChar(userDefFrom)){
                    sGetUserDef = sUserDef + " OR " + getUserDef;
                    if(isRelationWord){  //relatioanal word
                      List relationalUserDefList = dmsRelationalWordDaobject.getRelationalWordListByKeyWord(userDefFrom);
                      for(int i=0;i<relationalUserDefList.size();i++){
                        dmsRelationalWord = (DmsRelationalWord)relationalUserDefList.get(i);
                        String relationUserDef = dmsRelationalWord.getWord();
                        sGetUserDef += " OR " + TextUtility.convert(relationUserDef) + " OR " +relationUserDef ;
                      }
                    }
                  }
                  
                  HashMap mResult = getCriteriaCombination("D.USER_DEF_" + udfIdx, sGetUserDef, userDefExactMatch);
                  sqlStat.append(mResult.get("SQL"));
                  repe += TextUtility.parseInteger( (String) mResult.get("?"));
                  mFieldMap.put("USER_DEF_" + udfIdx+"_"+k, mResult.get("fieldResult"));
                }
              }
            }          
            
            
            if (!Utility.isEmpty(docDetailList)) {
              int tempCounter = 0;
              //sqlStat.append(" AND DD.USER_DEFINED_FIELD_ID =" + docDetail.getUserDefinedFieldID().toString() + "  AND (");
              int fieldTmpCount = 0;
              int a = 0;
              
              ListDmsDocumentForm tmpSearchObject = (ListDmsDocumentForm) searchFormList.get(k);
              docDetailList = tmpSearchObject.getDocumentDetails();
              
              docDetailList = docRetrievalManager.sortDocDetailList(docDetailList);
              
              for (int i = 0; i < docDetailList.size(); i++) {
                
                docDetail = (DmsDocumentDetail) docDetailList.get(i);
                
                int pos = 0;
                pos = i + 1;
                
                if (!Utility.isEmpty(docDetail.getFieldValue()) ||
                    docDetail.getDateValue() != null ||
                    docDetail.getToDateValue() != null ||
                    docDetail.getNumericValue() != null ||
                    docDetail.getToNumericValue() != null) {
                  fieldTmpCount++;
                  if (a == 0) {
                    sqlStat.append("  AND (");
                  } else if (a > 0) {
                    sqlStat.append(" AND ");
                  }
                  
                  //sqlStat.append(" ( DD.USER_DEFINED_FIELD_DETAIL_ID = " + docDetail.getUserDefinedFieldDetailID().toString());
                  //sqlStat.append(" ( DI.USER_DEFINED_FIELD_DETAIL_ID = " + docDetail.getUserDefinedFieldDetailID().toString());
                  sqlStat.append("( ");
                  
//                if (SysUserDefinedIndexDetail.STRING_FIELD.equals(docDetail.
//                getFieldType()) && !Utility.isEmpty(docDetail.getFieldValue())) {
                  
                  if (SysUserDefinedIndexDetail.STRING_FIELD.equals(docDetail.getFieldType())) {
                    log.debug("each field:" + docDetail.getFieldValue());
                    //HashMap mResult = (HashMap) getCriteriaCombination("DD.FIELD_VALUE", docDetail.getFieldValue(), true);
                    String sFieldValue=docDetail.getFieldValue();
                    String sValue=TextUtility.convert(sFieldValue);//convert big5 to gb or gb to big5
                    String sGetFieldValue=sFieldValue;
                    
                    if(!TextUtility.checkContainsOperandChar(docDetail.getFieldValue())){
                      sGetFieldValue=sFieldValue+" OR "+sValue;
                      if(isRelationWord){//relatioanal word
                        List relationalFieldValueList = dmsRelationalWordDaobject.getRelationalWordListByKeyWord(docDetail.getFieldValue());
                        for(int n=0;n<relationalFieldValueList.size();n++){
                          dmsRelationalWord = (DmsRelationalWord)relationalFieldValueList.get(n);
                          String relationFieldValue = dmsRelationalWord.getWord();
                          sGetFieldValue += " OR " + TextUtility.convert(relationFieldValue) + " OR " +relationFieldValue ;
                        }
                      }
                    } 
                    HashMap mResult = getCriteriaCombination("DI.INDEX_" + pos, sGetFieldValue, docDetail.getExactMatch());
                    
                    sqlStat.append(mResult.get("SQL"));
                    repe += TextUtility.parseInteger( (String) mResult.get("?"));
                    
                    List tmpList = (List) mResult.get("fieldResult");
                    mFieldMap.put("UDF_DETAIL_" + docDetail.getUserDefinedFieldDetailID() + "_FIELDVALUE_" + k, mResult.get("fieldResult"));
                    
                  }else if (SysUserDefinedIndexDetail.FIELD_TYPE_SELECT_DATABASE.equals(docDetail.getFieldType())) {
                    log.debug("each field:" + docDetail.getFieldValue());
                    //HashMap mResult = (HashMap) getCriteriaCombination("DD.FIELD_VALUE", docDetail.getFieldValue(), true);
                    String sFieldValue=docDetail.getFieldValue();
                    String sValue=TextUtility.convert(sFieldValue);//convert big5 to gb or gb to big5
                    String sGetFieldValue=sFieldValue;
                    
                    if(!TextUtility.checkContainsOperandChar(docDetail.getFieldValue())){
                      sGetFieldValue=sFieldValue+" OR "+sValue;
                      if(isRelationWord){//relatioanal word
                        List relationalFieldValueList = dmsRelationalWordDaobject.getRelationalWordListByKeyWord(docDetail.getFieldValue());
                        for(int n=0;n<relationalFieldValueList.size();n++){
                          dmsRelationalWord = (DmsRelationalWord)relationalFieldValueList.get(n);
                          String relationFieldValue = dmsRelationalWord.getWord();
                          sGetFieldValue += " OR " + TextUtility.convert(relationFieldValue) + " OR " +relationFieldValue ;
                        }
                      }
                    } 
                    HashMap mResult = getCriteriaCombination("DI.INDEX_" + pos, sGetFieldValue, true);
                    
                    sqlStat.append(mResult.get("SQL"));
                    repe += TextUtility.parseInteger( (String) mResult.get("?"));
                    
                    List tmpList = (List) mResult.get("fieldResult");
                    mFieldMap.put("UDF_DETAIL_" + docDetail.getUserDefinedFieldDetailID() + "_FIELDVALUE_" + k, mResult.get("fieldResult"));
                    
                  } else if (SysUserDefinedIndexDetail.NUMBER_FIELD.equals(docDetail.getFieldType())) { //number value
                    
                    if (docDetail.getNumericValue() != null && docDetail.getToNumericValue() != null) {
                      sqlStat.append(" (DI.INDEX_" + pos + ">= '" + IndexManager.numberPad(docDetail.getNumericValue()) + "' AND DI.INDEX_" + pos + " <= '" +
                          IndexManager.numberPad(docDetail.getToNumericValue()) + "' ) ");
                    } else if (docDetail.getNumericValue() != null && docDetail.getToNumericValue() == null) { //only first value entered
                      sqlStat.append(" (DI.INDEX_" + pos + " >= '" + IndexManager.numberPad(docDetail.getNumericValue()) + "' ) ");
                    } else if (docDetail.getNumericValue() == null && docDetail.getToNumericValue() != null) { //only 2nd value entered
                      sqlStat.append(" (DI.INDEX_" + pos + " <= '" + IndexManager.numberPad(docDetail.getToNumericValue()) + "' ) ");
                    }
                    
                  } else if (SysUserDefinedIndexDetail.DATE_FIELD.equals(docDetail. //Date range
                      getFieldType())) {
                    if (docDetail.getDateValue() != null && docDetail.getToDateValue() != null) {
                      // sqlStat.append(" (DI.INDEX_" + pos + " >= '" + DateField.dateToString(docDetail.getDateValue()) + "' AND DI.INDEX_" + pos + " <= '" +
                      //                DateField.dateToString(docDetail.getToDateValue()) + "' ) ");
                      
                      sqlStat.append(" (DI.INDEX_" + pos + " >= '" + TextUtility.formatTimestampToIndex(docDetail.getDateValue()) + "' AND DI.INDEX_" + pos + " <= '" +
                          TextUtility.formatTimestampToIndex(docDetail.getToDateValue()) + "' ) ");
                    } else if (docDetail.getDateValue() != null && docDetail.getToDateValue() == null) { //only first value entered
                      //sqlStat.append(" (DI.INDEX_" + pos + " >= '" + DateField.dateToString(docDetail.getDateValue()) + "' ) ");
                      sqlStat.append(" (DI.INDEX_" + pos + " >= '" + TextUtility.formatTimestampToIndex(docDetail.getDateValue()) + "' ) ");
                    } else if (docDetail.getDateValue() == null && docDetail.getToDateValue() != null) { //only 2nd value entered
                      //sqlStat.append(" (DI.INDEX_" + pos + " <= '" + DateField.dateToString(docDetail.getToDateValue()) + "' ) ");
                      sqlStat.append(" (DI.INDEX_" + pos + " <= '" + TextUtility.formatTimestampToIndex(docDetail.getToDateValue()) + "' ) ");
                    }
                  }
                  
                  sqlStat.append(" )   ");
                  if (a == 0) {
                    sqlStat.append(" )  ");
                  }
                  a++;
                }
              }
              repe++;
            }
            sqlStat.append(" ) ");
        }
        sqlStat.append(" ) ");
        
        sqlStat.append("AND ((D.EFFECTIVE_START_DATE IS NULL OR D.EFFECTIVE_START_DATE <= ?) OR D.OWNER_ID=?) ");
        if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
          sqlStat.append("       AND ((D.EFFECTIVE_END_DATE IS NULL OR D.EFFECTIVE_END_DATE > ?) ");
          sqlStat.append("       OR D.OWNER_ID = ?) ");
        }
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        //sqlStat.append("ORDER BY D.ID DESC ");
        
        sqlStat.append("ORDER BY D.DOCUMENT_TYPE DESC  ");
        
        if (docSearchForm.isSortable()) {
          
          String sortAttribute = docSearchForm.getSortAttribute();
          if (sortAttribute.indexOf(".") < 0) {
            sortAttribute = "D." + sortAttribute;
          }
          
          sqlStat.append(", " + sortAttribute + " " + searchForm.getSortOrder() + " ");
        }
        
        int i = 0;
        
        // Get total number of record return.
        StringBuffer sbResult = new StringBuffer("SELECT COUNT(DISTINCT(D.ID)) FROM ");
        int idx = sqlStat.indexOf("FROM ");
        sbResult.append(sqlStat.substring(idx + 5));
        if (sbResult.indexOf("ORDER BY") >= 0) {
          sbResult = new StringBuffer(sbResult.substring(0, sbResult.indexOf("ORDER BY") - 1));
        }
        log.info("COUNT SQL: " + sbResult);
        sqlStatCnt = sbResult;
        preStatCnt = dbConn.prepareStatement(sqlStatCnt.toString());
        
        for (int k = 0; k < searchFormList.size(); k++) {
          searchObject = (ListDmsDocumentForm) searchFormList.get(k);
          String tmp1Cnt[] = null;
          if (rootIDs.size() > 0) {
            for (int j = 0; j < rootIDs.size(); j++) {
              Integer rootID = TextUtility.parseIntegerObj( (String) rootIDs.get(j));
              setPrepareStatement(preStatCnt, ++i, rootID);
            }
          } else {
            setPrepareStatement(preStatCnt, ++i, searchObject.getRootID());
          }
          
          if (!Utility.isEmpty(searchObject.getDocumentName())) {
            List fieldList = (List) mFieldMap.get("DOCUMENT_NAME_" + k);
            for (int j = 0; j < fieldList.size(); j++) {
              setPrepareStatement(preStatCnt, ++i, (String) fieldList.get(j));
            }
          }
          
          if (!Utility.isEmpty(searchObject.getReferenceNo())) {
            List fieldList = (List) mFieldMap.get("REFERENCE_NO_" + k);
            for (int j = 0; j < fieldList.size(); j++) {
              setPrepareStatement(preStatCnt, ++i, (String) fieldList.get(j));
            }
          }
          
          if (!Utility.isEmpty(searchObject.getDescription())) {
            List fieldList = (List) mFieldMap.get("DESCRIPTION_" + k);
            for (int j = 0; j < fieldList.size(); j++) {
              setPrepareStatement(preStatCnt, ++i, (String) fieldList.get(j));
            }
          }
          
          
          //iterate userDef1 to userDef10 using reflection
          for(int udfIdx = 1 ; udfIdx<=10 ; udfIdx++){
            Class cls = Class.forName(ListDmsDocumentForm.class.getName());
            Method userDefMethod = cls.getMethod("getUserDef"+udfIdx,null);
            String userDefFrom = (String)userDefMethod.invoke(searchObject, null);
            Method userDefToMethod = cls.getMethod("getUserDef"+udfIdx+"To",null);
            String userDefTo = (String)userDefToMethod.invoke(searchObject, null);
            Method userDefDataTypeMethod = cls.getMethod("getUserDef"+udfIdx+"DataType",null);
            String userDefDataType = (String)userDefDataTypeMethod.invoke(searchObject, null);
            
            
            if ( (!Utility.isEmpty(userDefFrom)) || (!Utility.isEmpty(userDefTo))) {
              if (DmsDefaultProfileSetting.FIELD_TYPE_DATE.equals(userDefDataType)) {
                List fieldList = (List) mFieldMap.get("USER_DEF_"+udfIdx+"_" + k);
                for (int j = 0; j < fieldList.size(); j++) {
                  setPrepareStatement(preStatCnt, ++i, (String) fieldList.get(j));
                }              
              }else{
                List fieldList = (List) mFieldMap.get("USER_DEF_"+udfIdx+"_" + k);
                for (int j = 0; j < fieldList.size(); j++) {
                  setPrepareStatement(preStatCnt, ++i, (String) fieldList.get(j));
                }  
              }          
            }
          }          
          
          
          if (!Utility.isEmpty(docDetailList)) {
            for (int j = 0; j < docDetailList.size(); j++) {
              docDetail = (DmsDocumentDetail) docDetailList.get(
                  j);
              List fieldList = (List) mFieldMap.get("UDF_DETAIL_" + docDetail.getUserDefinedFieldDetailID() + "_FIELDVALUE_" + k);
              if (!Utility.isEmpty(fieldList)) {
                for (int o = 0; o < fieldList.size(); o++) {
                  setPrepareStatement(preStatCnt, ++i, (String) fieldList.get(o));
                }
              }
            }
          }
        }
        
        this.setPrepareStatement(preStatCnt, ++i, currTime);
        this.setPrepareStatement(preStatCnt, ++i, this.sessionContainer.getUserRecordID());
        if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
          this.setPrepareStatement(preStatCnt, ++i, oneDayBeforeCurrTime);
          this.setPrepareStatement(preStatCnt, ++i, this.sessionContainer.getUserRecordID());
        }
        
        rsCnt = preStatCnt.executeQuery();
        if (rsCnt.next()) {
          totalNumOfRecord = rsCnt.getInt(1);
        }
        try {
          rsCnt.close();
        } catch (Exception ignore) {} finally {
          rsCnt = null;
        }
        try {
          preStatCnt.close();
        } catch (Exception ignore) {} finally {
          preStatCnt = null;
        }
        
        if (!DmsOperationConstant.SEARCH_RESULT_ALL.equals(docSearchForm.getSearchResultOpt())) {
          // Retrieve the result in row basis.
          sqlStat = this.getSelectListSQL(sqlStat, startOffset, pageSize);
        } else {
          log.info("SELECT SQL: " + sqlStat);
        }
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        
        String tmp1[] = null;
        i = 0;
        for (int k = 0; k < searchFormList.size(); k++) {
          searchObject = (ListDmsDocumentForm)
          searchFormList.get(k);
          if (rootIDs.size() > 0) {
            for (int j = 0; j < rootIDs.size(); j++) {
              Integer rootID = TextUtility.parseIntegerObj( (String) rootIDs.get(j));
              setPrepareStatement(preStat, ++i, rootID);
            }
          } else {
            setPrepareStatement(preStat, ++i, searchObject.getRootID());
          }
          
          if (!Utility.isEmpty(searchObject.getDocumentName())) {
            List fieldList = (List) mFieldMap.get("DOCUMENT_NAME_" + k);
            for (int j = 0; j < fieldList.size(); j++) {
              setPrepareStatement(preStat, ++i, (String) fieldList.get(j));
            }
          }
          
          if (!Utility.isEmpty(searchObject.getReferenceNo())) {
            List fieldList = (List) mFieldMap.get("REFERENCE_NO_" + k);
            for (int j = 0; j < fieldList.size(); j++) {
              setPrepareStatement(preStat, ++i, (String) fieldList.get(j));
            }
          }
          
          if (!Utility.isEmpty(searchObject.getDescription())) {
            List fieldList = (List) mFieldMap.get("DESCRIPTION_" + k);
            for (int j = 0; j < fieldList.size(); j++) {
              setPrepareStatement(preStat, ++i, (String) fieldList.get(j));
            }
          }
          
          //iterate userDef1 to userDef10 using reflection
          for(int udfIdx = 1 ; udfIdx<=10 ; udfIdx++){
            Class cls = Class.forName(ListDmsDocumentForm.class.getName());
            Method userDefMethod = cls.getMethod("getUserDef"+udfIdx,null);
            String userDefFrom = (String)userDefMethod.invoke(searchObject, null);
            Method userDefToMethod = cls.getMethod("getUserDef"+udfIdx+"To",null);
            String userDefTo = (String)userDefToMethod.invoke(searchObject, null);
            Method userDefDataTypeMethod = cls.getMethod("getUserDef"+udfIdx+"DataType",null);
            String userDefDataType = (String)userDefDataTypeMethod.invoke(searchObject, null);
            
            
            if ( (!Utility.isEmpty(userDefFrom)) || (!Utility.isEmpty(userDefTo))) {
              if (DmsDefaultProfileSetting.FIELD_TYPE_DATE.equals(userDefDataType)) {
                List fieldList = (List) mFieldMap.get("USER_DEF_"+udfIdx+"_" + k);
                for (int j = 0; j < fieldList.size(); j++) {
                  setPrepareStatement(preStat, ++i, (String) fieldList.get(j));
                }              
              } else{
                List fieldList = (List) mFieldMap.get("USER_DEF_"+udfIdx+"_" + k);
                for (int j = 0; j < fieldList.size(); j++) {
                  setPrepareStatement(preStat, ++i, (String) fieldList.get(j));
                }  
              }          
            }
          }         
          
          if (!Utility.isEmpty(docDetailList)) {
            for (int j = 0; j < docDetailList.size(); j++) {
              docDetail = (DmsDocumentDetail) docDetailList.get(j);
              List fieldList = (List) mFieldMap.get("UDF_DETAIL_" + docDetail.getUserDefinedFieldDetailID() + "_FIELDVALUE_" + k);
              if (!Utility.isEmpty(fieldList)) {
                for (int o = 0; o < fieldList.size(); o++) {
                  setPrepareStatement(preStat, ++i, (String) fieldList.get(o));
                }
              }
            }
          }
        }
        
        this.setPrepareStatement(preStat, ++i, currTime);
        this.setPrepareStatement(preStat, ++i, this.sessionContainer.getUserRecordID());
        if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
          this.setPrepareStatement(preStat, ++i, oneDayBeforeCurrTime);
          this.setPrepareStatement(preStat, ++i, this.sessionContainer.getUserRecordID());
        }
        
        rs = preStat.executeQuery();
        this.positionCursor(rs, startOffset, pageSize);
        
        while (rs.next() && rowLoopCnt < pageSize) {
          DmsDocument tmpDmsDocument = new DmsDocument();
          tmpDmsDocument.setID(getResultSetInteger(rs, "ID"));
          tmpDmsDocument.setDocumentName(getResultSetString(rs, "DOCUMENT_NAME"));
          tmpDmsDocument.setDocumentType(getResultSetString(rs, "DOCUMENT_TYPE"));
          tmpDmsDocument.setParentID(getResultSetInteger(rs, "PARENT_ID"));
          tmpDmsDocument.setRootID(getResultSetInteger(rs, "ROOT_ID"));
          tmpDmsDocument.setPriority(getResultSetString(rs, "PRIORITY"));
          tmpDmsDocument.setCreateType(getResultSetString(rs, "CREATE_TYPE"));
          tmpDmsDocument.setEffectiveStartDate(getResultSetTimestamp(rs, "EFFECTIVE_START_DATE"));
          tmpDmsDocument.setEffectiveEndDate(getResultSetTimestamp(rs, "EFFECTIVE_END_DATE"));
          tmpDmsDocument.setReminderAmount(getResultSetInteger(rs, "REMINDER_AMOUNT"));
          tmpDmsDocument.setReminderType(getResultSetString(rs, "REMINDER_TYPE"));
          tmpDmsDocument.setNotificationWay(getResultSetStringAry(rs, "NOTIFICATION_WAY", ";"));
          tmpDmsDocument.setOwnerID(getResultSetInteger(rs, "OWNER_ID"));
          tmpDmsDocument.setReferenceNo(getResultSetString(rs, "REFERENCE_NO"));
          tmpDmsDocument.setDescription(getResultSetString(rs, "DESCRIPTION"));
          tmpDmsDocument.setItemSize(getResultSetInteger(rs, "ITEM_SIZE"));
          tmpDmsDocument.setItemStatus(getResultSetString(rs, "ITEM_STATUS"));
          tmpDmsDocument.setCheckoutID(getResultSetInteger(rs, "CHECKOUT_ID"));
          tmpDmsDocument.setAlertEditID(getResultSetInteger(rs, "ALERT_EDIT_ID"));
          tmpDmsDocument.setAlertInviteID(getResultSetInteger(rs, "ALERT_INVITE_ID"));
          tmpDmsDocument.setExtRef(getResultSetString(rs, "EXT_REF"));           
          tmpDmsDocument.setUserDef1(getResultSetString(rs, "USER_DEF_1"));
          tmpDmsDocument.setUserDef2(getResultSetString(rs, "USER_DEF_2"));
          tmpDmsDocument.setUserDef3(getResultSetString(rs, "USER_DEF_3"));
          tmpDmsDocument.setUserDef4(getResultSetString(rs, "USER_DEF_4"));
          tmpDmsDocument.setUserDef5(getResultSetString(rs, "USER_DEF_5"));
          tmpDmsDocument.setUserDef6(getResultSetString(rs, "USER_DEF_6"));
          tmpDmsDocument.setUserDef7(getResultSetString(rs, "USER_DEF_7"));
          tmpDmsDocument.setUserDef8(getResultSetString(rs, "USER_DEF_8"));
          tmpDmsDocument.setUserDef9(getResultSetString(rs, "USER_DEF_9"));
          tmpDmsDocument.setUserDef10(getResultSetString(rs, "USER_DEF_10"));
          tmpDmsDocument.setRecordStatus(getResultSetString(rs, "RECORD_STATUS"));
          tmpDmsDocument.setUpdateCount(getResultSetInteger(rs, "UPDATE_COUNT"));
          tmpDmsDocument.setCreatorID(getResultSetInteger(rs, "CREATOR_ID"));
          tmpDmsDocument.setCreateDate(getResultSetTimestamp(rs, "CREATE_DATE"));
          tmpDmsDocument.setUpdaterID(getResultSetInteger(rs, "UPDATER_ID"));
          tmpDmsDocument.setUpdateDate(getResultSetTimestamp(rs, "UPDATE_DATE"));
          
          if (searchObject.getUserDefinedFieldID() != null) {
            tmpDmsDocument.setUserDefinedFieldID(getResultSetInteger(rs,
            "USER_DEFINED_FIELD_ID"));
          }
          
          //tmpDmsDocument.setCreatorName(UserInfoFactory.getUserFullName(tmpDmsDocument.getCreatorID()));
          tmpDmsDocument.setUpdaterName(UserInfoFactory.getUserFullName(tmpDmsDocument.getUpdaterID()));
          tmpDmsDocument.setRecordCount(totalNumOfRecord);
          tmpDmsDocument.setRowNum(startOffset++);
          if (!DmsOperationConstant.SEARCH_RESULT_ALL.equals(docSearchForm.getSearchResultOpt())) {
            ++rowLoopCnt;
          }
          
          
          result.add(tmpDmsDocument);
          
          
        }
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
        try {
          rsCnt.close();
        } catch (Exception ignore) {} finally {
          rsCnt = null;
        }
        try {
          preStatCnt.close();
        } catch (Exception ignore) {} finally {
          preStatCnt = null;
        }
      }
    }
  }
  
  /*
   * Updates the value of specified field in the table DMS_DOCUMENT
   * @param sqlType the SQL transaction type (UPDATE)
   * @param targetUpdateField the field in the DMS_DOCUMENT 
   * @param updateValue the value updated
   * @param obj AbstractBaseObject object (mainly DmsDocument object)
   * @return the updated AbstractBaseObject object (mainly DmsDocument object)
   * @throws ApplicationException
   */
  public synchronized AbstractBaseObject documentSQLExecute(String sqlType, String targetUpdateField, String updateValue, AbstractBaseObject obj) throws ApplicationException {
    return this.documentSQLExecute(sqlType, targetUpdateField, updateValue, obj, true);
  }
  
  /**
   * Updates the value of specified field in the table DMS_DOCUMENT 
   * @param sqlType the SQL transaction type (UPDATE)
   * @param targetUpdateField the field in the DMS_DOCUMENT 
   * @param updateValue the value updated
   * @param obj AbstractBaseObject object (mainly DmsDocument object)
   * @param isUpdateUpdtor is update update_date update_count and update_id or not / EIP-1438 07/01/11 LEE
   * @return the updated AbstractBaseObject object (mainly DmsDocument object)
   * @throws ApplicationException
   * 
   * <pre>
   * 
   *            ApplicationException with the following message codes will be thrown
   *            ErrorConstant.DB_CONCURRENT_ERROR - No record updated
   *            ErrorConstant.ErrorConstant.DB_GENERAL_ERROR - General caught SQLException
   *            ErrorConstant.DB_SELECT_ERROR - All kind of caught Exception
   *  
   * </pre>
   */
  public synchronized AbstractBaseObject documentSQLExecute(String sqlType, String targetUpdateField, String updateValue, AbstractBaseObject obj, boolean isUpdateUpdator) throws ApplicationException {
    PreparedStatement preStat = null;
    StringBuffer sqlStat = new StringBuffer();
    DmsDocument tmpDmsDocument = (DmsDocument) ( (DmsDocument) obj).clone();
    
    synchronized (dbConn) {
      try {
        int updateCnt = 0;
        Timestamp currTime = Utility.getCurrentTimestamp();
        sqlStat.append(sqlType + " DMS_DOCUMENT ");
        sqlStat.append("SET  " + targetUpdateField + "=? ");
        if (isUpdateUpdator) {
          sqlStat.append(", UPDATE_COUNT=?, UPDATER_ID=?, UPDATE_DATE=? ");
        }
        sqlStat.append("WHERE  ID=? AND UPDATE_COUNT=? ");
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        int counter = 1;
        setPrepareStatement(preStat, counter++, updateValue);
        if (isUpdateUpdator) {
          setPrepareStatement(preStat, counter++, new Integer(tmpDmsDocument.getUpdateCount().intValue() + 1));
          setPrepareStatement(preStat, counter++, sessionContainer.getUserRecordID());
          setPrepareStatement(preStat, counter++, currTime);
        }
        setPrepareStatement(preStat, counter++, tmpDmsDocument.getID());
        setPrepareStatement(preStat, counter++, tmpDmsDocument.getUpdateCount());
        updateCnt = preStat.executeUpdate();
        if (updateCnt == 0) {
          throw new ApplicationException(ErrorConstant.DB_CONCURRENT_ERROR);
        } else {
          tmpDmsDocument.setUpdaterID(sessionContainer.getUserRecordID());
          tmpDmsDocument.setUpdateDate(currTime);
          tmpDmsDocument.setUpdateCount(new Integer(tmpDmsDocument.getUpdateCount().intValue() + 1));
          tmpDmsDocument.setCreatorName(UserInfoFactory.getUserFullName(tmpDmsDocument.getCreatorID()));
          tmpDmsDocument.setUpdaterName(UserInfoFactory.getUserFullName(tmpDmsDocument.getUpdaterID()));
          return (tmpDmsDocument);
        }
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_UPDATE_ERROR, e);
      } finally {
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  /**
   * Gets list of the dmsDocument object(s) in all document type that are archived.
   * <PRE>
   * 
   * The archived dmsDocument get can be limited by specifiying:
   * 1. parent ID - the archived document(s) under the specified folder
   * 2. root ID - the archived document(s) under the specifid root
   * 3. dateFrom - the archived document(s) create after dateFrom
   * 4. dateTo - the archive document(s) create before dateTo
   * 5. userDefinedIndex - the archived document(s) with specifid document profile
   * 6. recordStatus - record status of the archived document(s)
   * </PRE>
   * 
   * @param parentID the document parent ID
   * @param rootID  the document root ID
   * @param dateFrom the document create date after this specified date
   * @param dateTo the document create date before this specified date
   * @param userDefinedIndex String array of User defined profile ID {@link com.dcivision.framework.bean.SysUserDefinedIndex} 
   * @param recordStatus the document record status
   * @return list of DmsDocument object(s)
   * @throws ApplicationException
   * <pre>
   * 
   *            ApplicationException with the following message codes will be thrown
   *            ErrorConstant.ErrorConstant.DB_GENERAL_ERROR - General caught SQLException
   *            ErrorConstant.DB_SELECT_ERROR - All kind of caught Exception
   *  
   * </pre>
   * @deprecated This method has deprecated.
   */
  public synchronized List getArchiveList(Integer parentID, Integer rootID, String startDate, String endDate, String[] userDefinedIndex, String recordStatus) throws ApplicationException {
    return (this.getArchiveList(parentID, rootID, startDate, endDate, userDefinedIndex, recordStatus, "*",false));
  }
  
  /**
   * 
   * @param parentID
   * @param rootID
   * @param dateFrom
   * @param dateTo
   * @param userDefinedIndex
   * @param recordStatus
   * @param documentType
   * @param isFolder
   * @return
   * @throws ApplicationException
   * @deprecated This method has deprecated.
   */
  public synchronized List getArchiveList(Integer parentID, Integer rootID, String dateFrom, String dateTo, String[] userDefinedIndex, String recordStatus, String documentType,boolean isFolder) throws
  ApplicationException {
    return (this.getArchiveList(parentID, rootID, dateFrom, dateTo, userDefinedIndex, recordStatus, "*",false,null));
  }
  
  /**
   * Gets list of the dmsDocument object(s) that are archived.
   * <PRE>
   * 
   * The archived dmsDocument get can be limited by specifiying:
   * 1. parent ID - the archived document(s) under the specified folder
   * 2. root ID - the archived document(s) under the specifid root
   * 3. dateFrom - the archived document(s) create after dateFrom
   * 4. dateTo - the archive document(s) create before dateTo
   * 5. userDefinedIndex - the archived document(s) with specifid document profile
   * 6. recordStatus - record status of the archived document(s)
   * 7. documentType - the archived document(s) with the document type, value "*" means all document type 
   * </PRE>
   * 
   * @param parentID the document parent ID
   * @param rootID  the document root ID
   * @param dateFrom the document create date after this specified date
   * @param dateTo the document create date before this specified date
   * @param userDefinedIndex String array of User defined profile ID {@link com.dcivision.framework.bean.SysUserDefinedIndex} 
   * @param recordStatus the document record status
   * @param documentType the document type {@link com.dcivision.dms.bean.DmsDocument#DOCUMENT_TYPE},
   *                                       {@link com.dcivision.dms.bean.DmsDocument#COMPOUND_DOC_TYPE},
   *                                       {@link com.dcivision.dms.bean.DmsDocument#DOCUMENT_LINK},
   *                                       {@link com.dcivision.dms.bean.DmsDocument#FOLDER_TYPE} 
   * @return list of DmsDocument object(s)
   * @throws ApplicationException
   * <pre>
   * 
   *            ApplicationException with the following message codes will be thrown
   *            ErrorConstant.ErrorConstant.DB_GENERAL_ERROR - General caught SQLException
   *            ErrorConstant.DB_SELECT_ERROR - All kind of caught Exception
   *  
   * </pre>
   * @deprecated This method has deprecated.
   */
  public synchronized List getArchiveList(Integer parentID, Integer rootID, String dateFrom, String dateTo, String[] userDefinedIndex, String recordStatus, String documentType,boolean isFolder,Integer ownerID) throws
  ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    List result = new ArrayList();
    Timestamp currTime = Utility.getCurrentTimestamp();
    Timestamp oneDayBeforeCurrTime = Utility.addDay(currTime, -1);
    
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT DISTINCT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE,A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF,A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        if (userDefinedIndex != null) {
          sqlStat.append("LEFT JOIN DMS_DOCUMENT_DETAIL B ON B.DOCUMENT_ID=A.ID ");
        }
        sqlStat.append("WHERE  A.ROOT_ID = ? AND A.RECORD_STATUS = ? AND A.ITEM_STATUS <> ?  ");
        if (parentID != null) {
          sqlStat.append("AND A.PARENT_ID = ? ");
        }
        if (DataSourceFactory.getDatabaseType() == DataSourceFactory.DB_ORACLE) {
          if (!Utility.isEmpty(dateFrom)) {
            sqlStat.append("AND A.CREATE_DATE >= TO_DATE('" + dateFrom + "','"+ "YYYY-MM-DD HH24:MI:SS" +"')  ");
          }
          if (!Utility.isEmpty(dateTo)) {
            sqlStat.append("AND A.CREATE_DATE < TO_DATE('" + TextUtility.dbDateAdder(dateTo, 1) + "','" + "YYYY-MM-DD HH24:MI:SS" +"')  ");
          }
        }else{
          if (!Utility.isEmpty(dateFrom)) {
            sqlStat.append("AND A.CREATE_DATE >= '" + dateFrom + "'  ");
          }
          if (!Utility.isEmpty(dateTo)) {
            sqlStat.append("AND A.CREATE_DATE < '" + TextUtility.dbDateAdder(dateTo, 1) + "'  ");
          }
        }
        if (!"*".equals(documentType)) {
          if(isFolder==true){
            sqlStat.append(" AND A.DOCUMENT_TYPE = ? ");
          }else{
            sqlStat.append(" AND A.DOCUMENT_TYPE <> ? ");
          }
        }
        if (userDefinedIndex != null) {
          sqlStat.append(" AND (");
          for (int i = 0; i < userDefinedIndex.length; i++) {
            sqlStat.append("B.USER_DEFINED_FIELD_ID = ? OR ");
          }
          sqlStat.delete(sqlStat.length() - 3, sqlStat.length());
          sqlStat.append(") ");
        }
        sqlStat.append("       AND (((A.EFFECTIVE_START_DATE IS NULL OR A.EFFECTIVE_START_DATE <= ?) ");
        sqlStat.append("       AND (A.EFFECTIVE_END_DATE IS NULL OR A.EFFECTIVE_END_DATE > ?)) ");
        sqlStat.append("       OR A.OWNER_ID = ?) ");
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        sqlStat.append("ORDER BY A.DOCUMENT_TYPE ASC, A.DOCUMENT_NAME ASC ");
        
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        
        int i = 1;
        this.setPrepareStatement(preStat, i++, rootID);
        //log.debug("dao value - rootID: "+rootID);
        this.setPrepareStatement(preStat, i++, recordStatus);
        //log.debug("dao value - record status: "+recordStatus);
        this.setPrepareStatement(preStat, i++, DmsVersion.ARCHIVED_STATUS);
        if (parentID != null) {
          this.setPrepareStatement(preStat, i++, parentID);
          log.debug("dao value - parent id: " + parentID);
        }
        if (!"*".equals(documentType)) {
          this.setPrepareStatement(preStat, i++, documentType);
        }
        if (userDefinedIndex != null) {
          for (int j = 0; j < userDefinedIndex.length; j++) {
            this.setPrepareStatement(preStat, i++, userDefinedIndex[j]);
            log.debug("dao value - user defined index id: " + userDefinedIndex[j]);
          }
        }
        this.setPrepareStatement(preStat, i++, currTime);
        this.setPrepareStatement(preStat, i++, oneDayBeforeCurrTime);
        if(!Utility.isEmpty(ownerID)){
          this.setPrepareStatement(preStat, i++, ownerID);
        }else{
          this.setPrepareStatement(preStat, i++, this.sessionContainer.getUserRecordID());
        }
        rs = preStat.executeQuery();
        while (rs.next()) {
          //if (!DmsDocument.FOLDER_TYPE.equals(getResultSetString(rs, "DOCUMENT_TYPE"))) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          result.add(tmpDmsDocument);
          /*} else {
           result.addAll(getArchiveList(getResultSetInteger(rs, "ID"), rootID, dateFrom, dateTo, userDefinedIndex, recordStatus, documentType));
           }*/
        }
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle,
            sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  /**
   * 
   * @param parentID
   * @param rootID
   * @param dateFrom
   * @param dateTo
   * @param userDefinedIndex
   * @param recordStatus
   * @param documentTypes
   * @param reverse
   * @param ownerID
   * @return
   * @throws ApplicationException
   * @deprecated This method has deprecated.
   */
  public synchronized List getArchiveList(Integer[] parentID, Integer rootID, String dateFrom, String dateTo, String[] userDefinedIndex, String recordStatus, String[] documentTypes, boolean reverse, Integer ownerID) throws  ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    List result = new ArrayList();
    try {
      sqlStat.append("SELECT DISTINCT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE,A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF,A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
      sqlStat.append("FROM   DMS_DOCUMENT A ");
      if (userDefinedIndex != null) {
        sqlStat.append("LEFT JOIN DMS_DOCUMENT_DETAIL B ON B.DOCUMENT_ID=A.ID ");
      }
      sqlStat.append("WHERE  A.ROOT_ID = ? AND A.RECORD_STATUS = ? AND A.ITEM_STATUS <> ?  ");
      sqlStat.append("AND A.PARENT_ID IN (");
      for (int i=0; i<parentID.length; i++) {
        sqlStat.append(i!=0?",?":"?");
      }
      sqlStat.append(") ");
      if (DataSourceFactory.getDatabaseType() == DataSourceFactory.DB_ORACLE) {
        if (!Utility.isEmpty(dateFrom)) {
          sqlStat.append("AND A.CREATE_DATE >= TO_DATE('" + dateFrom + "','"+ "YYYY-MM-DD HH24:MI:SS" +"')  ");
        }
        if (!Utility.isEmpty(dateTo)) {
          sqlStat.append("AND A.CREATE_DATE < TO_DATE('" + TextUtility.dbDateAdder(dateTo, 1) + "','" + "YYYY-MM-DD HH24:MI:SS" +"')  ");
        }
      }else{
        if (!Utility.isEmpty(dateFrom)) {
          sqlStat.append("AND A.CREATE_DATE >= '" + dateFrom + "'  ");
        }
        if (!Utility.isEmpty(dateTo)) {
          sqlStat.append("AND A.CREATE_DATE < '" + TextUtility.dbDateAdder(dateTo, 1) + "'  ");
        }
      }
      sqlStat.append(" AND A.DOCUMENT_TYPE "+( reverse ? "NOT IN" : "IN")+"(");
      for (int i=0; i<documentTypes.length; i++) {
        sqlStat.append(i!=0?",?":"?");
      }
      sqlStat.append(") ");
      if (userDefinedIndex != null) {
        sqlStat.append(" AND (");
        for (int i = 0; i < userDefinedIndex.length; i++) {
          sqlStat.append("B.USER_DEFINED_FIELD_ID = ? OR ");
        }
        sqlStat.delete(sqlStat.length() - 3, sqlStat.length());
        sqlStat.append(") ");
      }
      sqlStat.append("       AND (((A.EFFECTIVE_START_DATE IS NULL OR A.EFFECTIVE_START_DATE <= ?) ");
      sqlStat.append("       AND (A.EFFECTIVE_END_DATE IS NULL OR A.EFFECTIVE_END_DATE > ?)) ");
      sqlStat.append("       OR A.OWNER_ID = ?) ");
      //format the sql for any 'LIKE' statement contained
      sqlStat = this.getFormattedSQL(sqlStat.toString());
      sqlStat.append("ORDER BY A.DOCUMENT_TYPE ASC, A.DOCUMENT_NAME ASC ");
      
      preStat = dbConn.prepareStatement(sqlStat.toString());
      
      int counter = 1;
      this.setPrepareStatement(preStat, counter++, rootID);
      this.setPrepareStatement(preStat, counter++, recordStatus);
      this.setPrepareStatement(preStat, counter++, DmsVersion.ARCHIVED_STATUS);
      for (int i=0; i<parentID.length; i++) {
        this.setPrepareStatement(preStat, counter++, parentID[i]);
      }
      for (int i=0; i<documentTypes.length; i++) {
        this.setPrepareStatement(preStat, counter++, documentTypes[i]);
      }
      if (userDefinedIndex != null) {
        for (int j = 0; j < userDefinedIndex.length; j++) {
          this.setPrepareStatement(preStat, counter++, userDefinedIndex[j]);
        }
      }
      this.setPrepareStatement(preStat, counter++, Utility.getCurrentTimestamp());
      this.setPrepareStatement(preStat, counter++, Utility.addDay(Utility.getCurrentTimestamp(), -1));
      if(!Utility.isEmpty(ownerID)){
        this.setPrepareStatement(preStat, counter++, ownerID);
      }else{
        this.setPrepareStatement(preStat, counter++, this.sessionContainer.getUserRecordID());
      }
      rs = preStat.executeQuery();
      while (rs.next()) {
        DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
        result.add(tmpDmsDocument);
      }
      return (result);
    } catch (ApplicationException appEx) {
      throw appEx;
    } catch (SQLException sqle) {
      log.error(sqle, sqle);
      throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle,
          sqle.toString());
    } catch (Exception e) {
      log.error(e, e);
      throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
    } finally {
      try { rs.close(); } catch (Exception ignore) {} finally { rs = null; }
      try { preStat.close(); } catch (Exception ignore) {} finally { preStat = null; }
    }
  }
  
  /**
   * Gets the list of the DmsDocument object(s) exclude folder type document by the given searchForm.
   * <P>
   * The method mainly used for getting the list of the document(s) in displaying with the paging support. 
   * </P>
   *
   * <PRE>
   * 
   * Basic search can be achieved by, e.g.
   * searchForm.setBasicSearchField("document_name");
   * searchForm.setBasicSearchType("=");
   * searchForm.setBasicSearchKeyword("XXXX.doc");
   * 
   * </PRE>
   * @param searchForm the search Form
   * @return list of Dmsdocument object(s)
   * @throws ApplicationException
   * <pre>
   * 
   *            ApplicationException with the following message codes will be thrown
   *            ErrorConstant.ErrorConstant.DB_GENERAL_ERROR - General caught SQLException
   *            ErrorConstant.DB_SELECT_ERROR - All kind of caught Exception
   *  
   * </pre>
   */
  public synchronized List getDocumentList(AbstractSearchForm searchForm) throws ApplicationException {
    PreparedStatement preStat = null;
    PreparedStatement preStatCnt = null;
    ResultSet rs = null;
    ResultSet rsCnt = null;
    StringBuffer sqlStat = new StringBuffer();
    StringBuffer sqlStatCnt = new StringBuffer();
    List result = new ArrayList();
    int totalNumOfRecord = 0;
    int rowLoopCnt = 0;
    int startOffset = TextUtility.parseInteger(searchForm.getCurStartRowNo());
    int pageSize = TextUtility.parseInteger(searchForm.getPageOffset());
    ListDmsDocumentForm docSearchForm = (ListDmsDocumentForm) searchForm;
    Timestamp currTime = Utility.getCurrentTimestamp();
    Timestamp oneDayBeforeCurrTime = Utility.addDay(currTime, -1);
    String parentModul = "";
    if( searchForm instanceof ListDmsSelectSingleForm ) {
      ListDmsSelectSingleForm sForm = (ListDmsSelectSingleForm) searchForm;
      parentModul = sForm.getParentModule();
    }
    
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE,A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF,A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        sqlStat.append("WHERE  A.RECORD_STATUS = ? AND (A.DOCUMENT_TYPE = ? OR A.DOCUMENT_TYPE = ? OR A.DOCUMENT_TYPE = ? OR A.DOCUMENT_TYPE = ? OR A.DOCUMENT_TYPE = ? ");
        if( ! DmsOperationConstant.LIST_COMPOUND_DOCUMENT.equals(parentModul)) {
          sqlStat.append(" OR A.DOCUMENT_TYPE = ? ");
        }
        sqlStat.append(" ) AND A.ROOT_ID = ? AND A.PARENT_ID = ? ");
        sqlStat.append("       AND (((A.EFFECTIVE_START_DATE IS NULL OR A.EFFECTIVE_START_DATE <= ?) ");
        sqlStat.append("       AND (A.EFFECTIVE_END_DATE IS NULL OR A.EFFECTIVE_END_DATE > ?)) ");
        sqlStat.append("       OR A.OWNER_ID = ?) ");
        
        
        // Form the WHERE clause for filtering.
        /*if (searchForm.isSearchable()) {
         String searchField = searchForm.getBasicSearchField();
         if (searchField.indexOf(".") < 0) {
         searchField = "A." + searchField;
         }
         sqlStat.append("AND  " + searchField + " " + searchForm.getBasicSearchType() + " ? ");
         }*/
        
        if (searchForm.isSearchable()) {
          String searchField = getSearchColumn(searchForm.getBasicSearchField());
          sqlStat.append("AND  " + searchField + " " + searchForm.getBasicSearchType() + " ? ");
        }
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        // Form the ORDER clause for sorting.
        sqlStat.append("ORDER BY A.DOCUMENT_TYPE DESC  ");
        if (searchForm.isSortable()) {
          String sortAttribute = searchForm.getSortAttribute();
          if (sortAttribute.indexOf(".") < 0) {
            sortAttribute = "A." + sortAttribute;
          }
          sqlStat.append(", " + sortAttribute + " " + searchForm.getSortOrder());
        }
        
        // Get total number of record return.
        sqlStatCnt = this.getSelectCountSQL(sqlStat);
        preStatCnt = dbConn.prepareStatement(sqlStatCnt.toString());
        int i = 0;
        this.setPrepareStatement(preStatCnt, ++i, GlobalConstant.RECORD_STATUS_ACTIVE);
        this.setPrepareStatement(preStatCnt, ++i, DmsDocument.DOCUMENT_TYPE);
        this.setPrepareStatement(preStatCnt, ++i, DmsDocument.PAPER_DOC_TYPE);
        this.setPrepareStatement(preStatCnt, ++i, DmsDocument.EMAIL_DOC_TYPE);  
        this.setPrepareStatement(preStatCnt, ++i, DmsDocument.FORM_DOC_TYPE);  
        this.setPrepareStatement(preStatCnt, ++i, DmsDocument.FLOW_DOC_TYPE);  
        if( ! DmsOperationConstant.LIST_COMPOUND_DOCUMENT.equals(parentModul)) {
          setPrepareStatement(preStatCnt, ++i, DmsDocument.COMPOUND_DOC_TYPE);
        }
        this.setPrepareStatement(preStatCnt, ++i, docSearchForm.getRootID());
        this.setPrepareStatement(preStatCnt, ++i, docSearchForm.getParentID());
        this.setPrepareStatement(preStatCnt, ++i, currTime);
        
        
        this.setPrepareStatement(preStatCnt, ++i, oneDayBeforeCurrTime);
        this.setPrepareStatement(preStatCnt, ++i, this.sessionContainer.getUserRecordID());
        
        
        if (searchForm.isSearchable()) {
          String searchKeyword = this.getFormattedKeyword(searchForm.getBasicSearchKeyword(), searchForm.getBasicSearchType());
          this.setPrepareStatement(preStatCnt, ++i, searchKeyword);
        }
        rsCnt = preStatCnt.executeQuery();
        if (rsCnt.next()) {
          totalNumOfRecord = rsCnt.getInt(1);
        }
        try {
          rsCnt.close();
        } catch (Exception ignore) {} finally {
          rsCnt = null;
        }
        try {
          preStatCnt.close();
        } catch (Exception ignore) {} finally {
          preStatCnt = null;
        }
        
        // Retrieve the result in row basis.
        sqlStat = this.getSelectListSQL(sqlStat, startOffset, pageSize);
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        i = 0;
        this.setPrepareStatement(preStat, ++i, GlobalConstant.RECORD_STATUS_ACTIVE);
        this.setPrepareStatement(preStat, ++i, DmsDocument.DOCUMENT_TYPE);
        this.setPrepareStatement(preStat, ++i, DmsDocument.PAPER_DOC_TYPE);
        this.setPrepareStatement(preStat, ++i, DmsDocument.EMAIL_DOC_TYPE);
        this.setPrepareStatement(preStat, ++i, DmsDocument.FORM_DOC_TYPE);
        this.setPrepareStatement(preStat, ++i, DmsDocument.FLOW_DOC_TYPE);
        if( ! DmsOperationConstant.LIST_COMPOUND_DOCUMENT.equals(parentModul)) {
          this.setPrepareStatement(preStat, ++i, DmsDocument.COMPOUND_DOC_TYPE);
        }
        this.setPrepareStatement(preStat, ++i, docSearchForm.getRootID());
        this.setPrepareStatement(preStat, ++i, docSearchForm.getParentID());
        this.setPrepareStatement(preStat, ++i, currTime);
        
        
        this.setPrepareStatement(preStat, ++i, oneDayBeforeCurrTime);
        this.setPrepareStatement(preStat, ++i, this.sessionContainer.getUserRecordID());
        
        
        if (searchForm.isSearchable()) {
          String searchKeyword = this.getFormattedKeyword(searchForm.getBasicSearchKeyword(), searchForm.getBasicSearchType());
          this.setPrepareStatement(preStat, ++i, searchKeyword);
        }
        rs = preStat.executeQuery();
        this.positionCursor(rs, startOffset, pageSize);
        
        while (rs.next() && rowLoopCnt < pageSize) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          tmpDmsDocument.setRecordCount(totalNumOfRecord);
          tmpDmsDocument.setRowNum(startOffset++);
          ++rowLoopCnt;
          result.add(tmpDmsDocument);
        }
        
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
        try {
          rsCnt.close();
        } catch (Exception ignore) {} finally {
          rsCnt = null;
        }
        try {
          preStatCnt.close();
        } catch (Exception ignore) {} finally {
          preStatCnt = null;
        }
      }
    }
  }
  
  /**
   * Gets the list of empty document (reference file) that the current user is the document(s) ownern and the document(s) is
   * not expired.
   *  
   * @param searchForm the ListDmsEmptyDocumentForm object
   * @return list of empty document(s)
   * @throws ApplicationException 
   * 
   * <pre>
   * 
   *            ApplicationException with the following message codes will be thrown
   *            ErrorConstant.ErrorConstant.DB_GENERAL_ERROR - General caught SQLException
   *            ErrorConstant.DB_SELECT_ERROR - All kind of caught Exception
   *  
   * </pre>
   */
  public synchronized List getEmptyDocumentList(AbstractSearchForm searchForm) throws ApplicationException {
    PreparedStatement preStat = null;
    PreparedStatement preStatCnt = null;
    ResultSet rs = null;
    ResultSet rsCnt = null;
    StringBuffer sqlStat = new StringBuffer();
    StringBuffer sqlStatCnt = new StringBuffer();
    List result = new ArrayList();
    int totalNumOfRecord = 0;
    int rowLoopCnt = 0;
    int startOffset = TextUtility.parseInteger(searchForm.getCurStartRowNo());
    int pageSize = TextUtility.parseInteger(searchForm.getPageOffset());
    ListDmsEmptyDocumentForm docEmptyForm = (ListDmsEmptyDocumentForm) searchForm;
    Timestamp currTime = Utility.getCurrentTimestamp();
    Timestamp oneDayBeforeCurrTime = Utility.addDay(currTime, -1);
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE,A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF,A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        sqlStat.append("WHERE  A.RECORD_STATUS = ? AND A.CREATOR_ID = ?  ");
        sqlStat.append("       AND (((A.EFFECTIVE_START_DATE IS NULL OR A.EFFECTIVE_START_DATE <= ?) ");
        sqlStat.append("       AND (A.EFFECTIVE_END_DATE IS NULL OR A.EFFECTIVE_END_DATE > ?)) ");
        sqlStat.append("       OR A.OWNER_ID = ?) ");
        
        // Form the WHERE clause for filtering.
        /*if (searchForm.isSearchable()) {
         String searchField = searchForm.getBasicSearchField();
         if (searchField.indexOf(".") < 0) {
         searchField = "A." + searchField;
         }
         sqlStat.append("AND  " + searchField + " " + searchForm.getBasicSearchType() + " ? ");
         }*/
        if (searchForm.isSearchable()) {
          String searchField = getSearchColumn(searchForm.getBasicSearchField());
          sqlStat.append("AND  " + searchField + " " + searchForm.getBasicSearchType() + " ? ");
        }
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        // Form the ORDER clause for sorting.
        sqlStat.append("ORDER BY A.DOCUMENT_TYPE DESC  ");
        if (searchForm.isSortable()) {
          String sortAttribute = searchForm.getSortAttribute();
          if (sortAttribute.indexOf(".") < 0) {
            sortAttribute = "A." + sortAttribute;
          }
          sqlStat.append(", " + sortAttribute + " " + searchForm.getSortOrder());
        }
        
        // Get total number of record return.
        sqlStatCnt = this.getSelectCountSQL(sqlStat);
        preStatCnt = dbConn.prepareStatement(sqlStatCnt.toString());
        this.setPrepareStatement(preStatCnt, 1, DmsOperationConstant.DMS_RECORD_EMPTY);
        this.setPrepareStatement(preStatCnt, 2, sessionContainer.getUserRecordID());
        this.setPrepareStatement(preStatCnt, 3, currTime);
        this.setPrepareStatement(preStatCnt, 4, oneDayBeforeCurrTime);
        this.setPrepareStatement(preStatCnt, 5, this.sessionContainer.getUserRecordID());
        if (searchForm.isSearchable()) {
          String searchKeyword = this.getFormattedKeyword(searchForm.getBasicSearchKeyword(), searchForm.getBasicSearchType());
          this.setPrepareStatement(preStatCnt, 6, searchKeyword);
        }
        rsCnt = preStatCnt.executeQuery();
        if (rsCnt.next()) {
          totalNumOfRecord = rsCnt.getInt(1);
        }
        try {
          rsCnt.close();
        } catch (Exception ignore) {} finally {
          rsCnt = null;
        }
        try {
          preStatCnt.close();
        } catch (Exception ignore) {} finally {
          preStatCnt = null;
        }
        
        // Retrieve the result in row basis.
        sqlStat = this.getSelectListSQL(sqlStat, startOffset, pageSize);
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, DmsOperationConstant.DMS_RECORD_EMPTY);
        this.setPrepareStatement(preStat, 2, sessionContainer.getUserRecordID());
        this.setPrepareStatement(preStat, 3, currTime);
        this.setPrepareStatement(preStat, 4, oneDayBeforeCurrTime);
        this.setPrepareStatement(preStat, 5, this.sessionContainer.getUserRecordID());
        if (searchForm.isSearchable()) {
          String searchKeyword = this.getFormattedKeyword(searchForm.getBasicSearchKeyword(), searchForm.getBasicSearchType());
          this.setPrepareStatement(preStat, 6, searchKeyword);
        }
        
        rs = preStat.executeQuery();
        
        this.positionCursor(rs, startOffset, pageSize);
        while (rs.next() && rowLoopCnt < pageSize) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          tmpDmsDocument.setRecordCount(totalNumOfRecord);
          tmpDmsDocument.setRowNum(startOffset++);
          ++rowLoopCnt;
          result.add(tmpDmsDocument);
        }
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
        try {
          rsCnt.close();
        } catch (Exception ignore) {} finally {
          rsCnt = null;
        }
        try {
          preStatCnt.close();
        } catch (Exception ignore) {} finally {
          preStatCnt = null;
        }
      }
    }
  }
  
  
  /**
   * Gets the active DmsDocument object by the given reference No.
   * 
   * @param referenceNo the reference no. of the document
   * @return the DmsDocument object
   * @throws ApplicationException
   * <pre>
   * 
   *            ApplicationException with the following message codes will be thrown
   *            ErrorConstant.ErrorConstant.DB_GENERAL_ERROR - General caught SQLException
   *            ErrorConstant.DB_SELECT_ERROR - All kind of caught Exception
   *  
   * </pre>
   * @see com.dcivision.dms.bean.DmsDocument
   */
  public synchronized AbstractBaseObject getObjectByReferenceNo(String referenceNo) throws ApplicationException {
    return getObjectByReferenceNo(null, referenceNo);
  }
  
  /**
   * Gets the active DmsDocument object by the given reference No.
   
   * @param recordStatus temporary no use
   * @param referenceNo the reference no. of the document
   * @return the DmsDocument object
   * @throws ApplicationException
   * <pre>
   * 
   *            ApplicationException with the following message codes will be thrown
   *            ErrorConstant.ErrorConstant.DB_GENERAL_ERROR - General caught SQLException
   *            ErrorConstant.DB_SELECT_ERROR - All kind of caught Exception
   *  
   * </pre>
   * @see com.dcivision.dms.bean.DmsDocument
   */
  public synchronized AbstractBaseObject getObjectByReferenceNo(String recordStatus, String referenceNo) throws ApplicationException {
    return getObjectByReferenceNo(GlobalConstant.RECORD_STATUS_ACTIVE, referenceNo, null);
  }
  
  /**
   * Gets the DmsDocument object by the given reference No.
   * <PRE>
   * The following arguments limit the dmsDocoument as the result:
   * 1. recordstatus - specified active or inactive document
   *                   {@link com.dcivision.framework.GlobalConstant#RECORD_STATUS_ACTIVE},
   *                   {@link com.dcivision.framework.GlobalConstant#RECORD_STATUS_INACTIVE},
   * 
   * 2. documentType - specified document type
   *                   {@link com.dcivision.dms.bean.DmsDocument#DOCUMENT_TYPE},{@link com.dcivision.dms.bean.DmsDocument#COMPOUND_DOC_TYPE},
   *                   {@link com.dcivision.dms.bean.DmsDocument#DOCUMENT_LINK},{@link com.dcivision.dms.bean.DmsDocument#FOLDER_TYPE},
   *                   ,"" or null means all document type 
   * 
   * </PRE>
   * @param recordStatus the record status of the document
   * @param referenceNo the reference no. of the document
   * @param documentType the document type
   * @return the DmsDocument object
   * @throws ApplicationException
   * <pre>
   * 
   *            ApplicationException with the following message codes will be thrown
   *            ErrorConstant.ErrorConstant.DB_GENERAL_ERROR - General caught SQLException
   *            ErrorConstant.DB_SELECT_ERROR - All kind of caught Exception
   *  
   * </pre>
   * @see com.dcivision.dms.bean.DmsDocument
   */
  public synchronized AbstractBaseObject getObjectByReferenceNo(String recordStatus, String referenceNo, String documentType) throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    DmsDocument tmpDmsDocument = new DmsDocument();
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE,A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID,A.EXT_REF, A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        sqlStat.append("WHERE  A.REFERENCE_NO = ? ");
        if (!Utility.isEmpty(recordStatus)) {
          sqlStat.append(" AND A.RECORD_STATUS = ?  ");
        }
        if (!Utility.isEmpty(documentType)) {
          sqlStat.append(" AND A.DOCUMENT_TYPE = ?  ");
        }
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, referenceNo);
        int tmpCnt = 2;
        if (!Utility.isEmpty(recordStatus)) {
          this.setPrepareStatement(preStat, tmpCnt++, recordStatus);
        }
        if (!Utility.isEmpty(documentType)) {
          this.setPrepareStatement(preStat, tmpCnt++, documentType);
        }
        
        rs = preStat.executeQuery();
        if (rs.next()) {
          tmpDmsDocument = parseObjectFromResultSet(rs);
          return (tmpDmsDocument);
        } else {
          return null;
        }
        
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  public synchronized int getNoOfVersion(Integer documentID) throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    int versions = 0;
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT COUNT(*) ");
        sqlStat.append("FROM   DMS_VERSION A ");
        sqlStat.append("WHERE  A.DOCUMENT_ID = ? ");
        
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, documentID);
        rs = preStat.executeQuery();
        if (rs.next()) {
          versions = rs.getInt(1);
        }
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
    return versions;
  }
  
  public synchronized void updateStatusByObjectID(Integer ID, String recordStatus) throws ApplicationException {
    PreparedStatement preStat = null;
    StringBuffer sqlStat = new StringBuffer();
    synchronized (dbConn) {
      try {
        sqlStat.append("UPDATE DMS_DOCUMENT ");
        sqlStat.append("SET    RECORD_STATUS = ? ");
        sqlStat.append("WHERE  ID = ? ");
        
        preStat = dbConn.prepareStatement(sqlStat.toString());
        this.setPrepareStatement(preStat, 1, recordStatus);
        this.setPrepareStatement(preStat, 2, ID);
        preStat.executeUpdate();
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  /**
   * getAllChildListByParentIDRootID - Used to copy all files no matter its status is active or not
   *
   * @param parentID      The parentID
   * @return List         The list of all child inside in the parent folder
   * @throws ApplicationException
   */
  
  public synchronized List getAllChildListByParentIDRootID(Integer parentID) throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    List result = new ArrayList();
    Timestamp currTime = Utility.getCurrentTimestamp();
    Timestamp oneDayBeforeCurrTime = Utility.addDay(currTime, -1);
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE,A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF,A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        sqlStat.append("WHERE  A.PARENT_ID = ? ");
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        sqlStat.append("ORDER BY A.DOCUMENT_TYPE ASC, A.DOCUMENT_NAME ASC ");
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, parentID);
        rs = preStat.executeQuery();
        while (rs.next()) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          result.add(tmpDmsDocument);
        }
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  
  
  public synchronized List getHomeDocumentList(AbstractSearchForm searchForm,String documentType,List availHomeList) throws ApplicationException {
    PreparedStatement preStat = null;
    PreparedStatement preStatCnt = null;
    ResultSet rs = null;
    ResultSet rsCnt = null;
    StringBuffer sqlStat = new StringBuffer();
    StringBuffer sqlStatCnt = new StringBuffer();
    List result = new ArrayList();
    int totalNumOfRecord = 0;
    int rowLoopCnt = 0;
    int startOffset = TextUtility.parseInteger(searchForm.getCurStartRowNo());
    int pageSize = TextUtility.parseInteger(searchForm.getPageOffset());
    ListDmsPaperDocumentForm paperDocForm = (ListDmsPaperDocumentForm) searchForm;
    Timestamp currTime = Utility.getCurrentTimestamp();
    Timestamp oneDayBeforeCurrTime = Utility.addDay(currTime, -1);
    synchronized (dbConn) {
      try {
        if(!DmsDocument.PAPER_DOC_TYPE.equals(documentType)){
          sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE, A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID,A.EXT_REF, A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
          sqlStat.append("FROM   DMS_DOCUMENT A ");
          //sqlStat.append("WHERE  A.RECORD_STATUS = ? AND A.CREATOR_ID = ?  AND A.DOCUMENT_TYPE = ? ");
          
        }else{
          /* sqlStat.append("SELECT * ");
           sqlStat.append("FROM DMS_DOCUMENT A LEFT JOIN DMS_DOCUMENT_INDEX DI ");
           sqlStat.append("ON A.ID = DI.DOCUMENT_ID ");
           */
          sqlStat.append("SELECT * ");
          sqlStat.append("FROM DMS_DOCUMENT A LEFT JOIN ");
          sqlStat.append("DMS_DOCUMENT_INDEX DI  ON A.ID = DI.DOCUMENT_ID ");
          sqlStat.append("LEFT JOIN  SYS_USER_DEFINED_INDEX S ON DI.USER_DEFINED_FIELD_ID = S.ID ");
          
        }
        
        sqlStat.append("WHERE  A.RECORD_STATUS = ? AND A.DOCUMENT_TYPE = ? ");
        
        //limit the list result for the home folder
        if(!Utility.isEmpty(availHomeList)){
          StringBuffer availHomeStr =new StringBuffer();
          for(int i=0;i<availHomeList.size();i++){
            DmsDocument tmpDmsDocument = (DmsDocument)availHomeList.get(i);
            if(i!=availHomeList.size()-1){
              availHomeStr.append(tmpDmsDocument.getID()+", ");
            }   
          }
          sqlStat.append("       AND "+getInSQL("A.PARENT_ID",availHomeStr.toString())  );
        }
        
        if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
          sqlStat.append("       AND (((A.EFFECTIVE_START_DATE IS NULL OR A.EFFECTIVE_START_DATE <= ?) ");
          sqlStat.append("       AND (A.EFFECTIVE_END_DATE IS NULL OR A.EFFECTIVE_END_DATE > ?)) ");
          sqlStat.append("       OR A.OWNER_ID = ?) ");
        }
        
        
        
        // Form the WHERE clause for filtering.
        /* if (searchForm.isSearchable()) {
         String searchField = searchForm.getBasicSearchField();
         if (searchField.indexOf(".") < 0) {
         searchField = "A." + searchField;
         }
         sqlStat.append("AND  " + searchField + " " + searchForm.getBasicSearchType() + " ? ");
         }*/
        if (searchForm.isSearchable()) {
          String searchField = getSearchColumn(searchForm.getBasicSearchField());
          sqlStat.append("AND  " + searchField + " " + searchForm.getBasicSearchType() + " ? ");
        }
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        // Form the ORDER clause for sorting.
        sqlStat.append("ORDER BY A.DOCUMENT_TYPE DESC  ");
        if (searchForm.isSortable()) {
          String sortAttribute = searchForm.getSortAttribute();
          if (sortAttribute.indexOf(".") < 0) {
            sortAttribute = "A." + sortAttribute;
          }
          sqlStat.append(", " + sortAttribute + " " + searchForm.getSortOrder());
        }
        
        // Get total number of record return.
        sqlStatCnt = this.getSelectCountSQL(sqlStat);
        preStatCnt = dbConn.prepareStatement(sqlStatCnt.toString());
        this.setPrepareStatement(preStatCnt, 1, GlobalConstant.RECORD_STATUS_ACTIVE);
        //this.setPrepareStatement(preStatCnt, 2, sessionContainer.getUserRecordID());
        if(documentType!=null){
          this.setPrepareStatement(preStatCnt, 2, documentType);   
        }else{
          this.setPrepareStatement(preStatCnt, 2, DmsDocument.COMPOUND_DOC_TYPE);
        }
        if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
          this.setPrepareStatement(preStatCnt, 3, currTime);
          this.setPrepareStatement(preStatCnt, 4, oneDayBeforeCurrTime);
          this.setPrepareStatement(preStatCnt, 5, this.sessionContainer.getUserRecordID());
        }
        
        if (searchForm.isSearchable()) {
          String searchKeyword = this.getFormattedKeyword(searchForm.getBasicSearchKeyword(), searchForm.getBasicSearchType());
          if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
            this.setPrepareStatement(preStatCnt, 6, searchKeyword);
          }else{
            this.setPrepareStatement(preStatCnt, 3, searchKeyword);
          }
          
        }
        rsCnt = preStatCnt.executeQuery();
        if (rsCnt.next()) {
          totalNumOfRecord = rsCnt.getInt(1);
        }
        try {
          rsCnt.close();
        } catch (Exception ignore) {} finally {
          rsCnt = null;
        }
        try {
          preStatCnt.close();
        } catch (Exception ignore) {} finally {
          preStatCnt = null;
        }
        
        
        
        
        
        
        // Retrieve the result in row basis.
        sqlStat = this.getSelectListSQL(sqlStat, startOffset, pageSize);
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, GlobalConstant.RECORD_STATUS_ACTIVE);
        //this.setPrepareStatement(preStat, 2, sessionContainer.getUserRecordID());
        if(documentType!=null){
          this.setPrepareStatement(preStat, 2, documentType);
        }else{
          this.setPrepareStatement(preStat, 2, DmsDocument.COMPOUND_DOC_TYPE);
        }
        if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
          this.setPrepareStatement(preStat, 3, currTime);
          this.setPrepareStatement(preStat, 4, oneDayBeforeCurrTime);
          this.setPrepareStatement(preStat, 5, this.sessionContainer.getUserRecordID());
        }
        
        if (searchForm.isSearchable()) {
          String searchKeyword = this.getFormattedKeyword(searchForm.getBasicSearchKeyword(), searchForm.getBasicSearchType());
          if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
            this.setPrepareStatement(preStat, 6, searchKeyword);
          }else{
            this.setPrepareStatement(preStat, 3, searchKeyword);
          }
        }
        
        rs = preStat.executeQuery();
        this.positionCursor(rs, startOffset, pageSize);
        while (rs.next() && rowLoopCnt < pageSize) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          tmpDmsDocument.setRecordCount(totalNumOfRecord);
          tmpDmsDocument.setRowNum(startOffset++);
          ++rowLoopCnt;   
          result.add(tmpDmsDocument);
        }
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
        try {
          rsCnt.close();
        } catch (Exception ignore) {} finally {
          rsCnt = null;
        }
        try {
          preStatCnt.close();
        } catch (Exception ignore) {} finally {
          preStatCnt = null;
        }
      }
    }
  }
  
  /**
   * Gets list of the compound document(s).
   * 
   * @param searchForm the ListDmsCompoundDocumentForm object
   *                
   * @return list of the DmsDocument object
   * @throws ApplicationException
   * <pre>
   * 
   *            ApplicationException with the following message codes will be thrown
   *            ErrorConstant.ErrorConstant.DB_GENERAL_ERROR - General caught SQLException
   *            ErrorConstant.DB_SELECT_ERROR - All kind of caught Exception
   *  
   * </pre>
   * 
   */
  public synchronized List getCompoundDocumentList(AbstractSearchForm searchForm) throws ApplicationException{
    return getCompoundDocumentList(searchForm,null);
  }
  
  /**
   * Gets list of the compound or paper document(s).
   * 
   * @param searchForm the ListDmsCompoundDocumentForm object
   * @param documentType the document type specified whether compound document or paper document as to be retrieved.
   *                     values:
   *                     Compound document - null or {@link com.dcivision.dms.bean.DmsDocument#COMPOUND_DOC_TYPE},
   *                     Paper document - {@link com.dcivision.dms.bean.DmsDocument#PAPER_DOC_TYPE}
   *                
   * @return list of the DmsDocument object
   * @throws ApplicationException
   * <pre>
   * 
   *            ApplicationException with the following message codes will be thrown
   *            ErrorConstant.ErrorConstant.DB_GENERAL_ERROR - General caught SQLException
   *            ErrorConstant.DB_SELECT_ERROR - All kind of caught Exception
   *  
   * </pre>
   * 
   */
  public synchronized List getCompoundDocumentList(AbstractSearchForm searchForm,String documentType) throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    List result = new ArrayList();
    ListDmsCompoundDocumentForm compoundDocForm = (ListDmsCompoundDocumentForm) searchForm;
    Timestamp currTime = Utility.getCurrentTimestamp();
    Timestamp oneDayBeforeCurrTime = Utility.addDay(currTime, -1);
    synchronized (dbConn) {
      try {
        if(!DmsDocument.PAPER_DOC_TYPE.equals(documentType)){
          sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE, A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF,A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
          sqlStat.append("FROM   DMS_DOCUMENT A ");
          //sqlStat.append("WHERE  A.RECORD_STATUS = ? AND A.CREATOR_ID = ?  AND A.DOCUMENT_TYPE = ? ");
          
        }else{
          /* sqlStat.append("SELECT * ");
           sqlStat.append("FROM DMS_DOCUMENT A LEFT JOIN DMS_DOCUMENT_INDEX DI ");
           sqlStat.append("ON A.ID = DI.DOCUMENT_ID ");
           */
          sqlStat.append("SELECT * ");
          sqlStat.append("FROM DMS_DOCUMENT A LEFT JOIN ");
          sqlStat.append("DMS_DOCUMENT_INDEX DI  ON A.ID = DI.DOCUMENT_ID ");
          sqlStat.append("LEFT JOIN  SYS_USER_DEFINED_INDEX S ON DI.USER_DEFINED_FIELD_ID = S.ID ");
          
        }
        
        sqlStat.append("WHERE  A.RECORD_STATUS = ? AND A.DOCUMENT_TYPE = ? ");
        sqlStat.append("AND ((A.EFFECTIVE_START_DATE IS NULL OR A.EFFECTIVE_START_DATE <= ?) OR A.OWNER_ID=?)");
        if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
          sqlStat.append("       AND ((A.EFFECTIVE_END_DATE IS NULL OR A.EFFECTIVE_END_DATE > ?) ");
          sqlStat.append("       OR A.OWNER_ID = ?) ");
        }
        
        
        // Form the WHERE clause for filtering.
        /* if (searchForm.isSearchable()) {
         String searchField = searchForm.getBasicSearchField();
         if (searchField.indexOf(".") < 0) {
         searchField = "A." + searchField;
         }
         sqlStat.append("AND  " + searchField + " " + searchForm.getBasicSearchType() + " ? ");
         }*/
        if (searchForm.isSearchable()) {
          String searchField = getSearchColumn(searchForm.getBasicSearchField());
          sqlStat.append("AND  " + searchField + " " + searchForm.getBasicSearchType() + " ? ");
        }
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        // Form the ORDER clause for sorting.
        sqlStat.append("ORDER BY A.DOCUMENT_TYPE DESC  ");
        if (searchForm.isSortable()) {
          String sortAttribute = searchForm.getSortAttribute();
          if (sortAttribute.indexOf(".") < 0) {
            sortAttribute = "A." + sortAttribute;
          }
          sqlStat.append(", " + sortAttribute + " " + searchForm.getSortOrder());
        }
        
        // Get total number of record return.
        
        // Retrieve the result in row basis.
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, GlobalConstant.RECORD_STATUS_ACTIVE);
        //this.setPrepareStatement(preStat, 2, sessionContainer.getUserRecordID());
        if(documentType!=null){
          this.setPrepareStatement(preStat, 2, documentType);
        }else{
          this.setPrepareStatement(preStat, 2, DmsDocument.COMPOUND_DOC_TYPE);
        }
        this.setPrepareStatement(preStat, 3, currTime);
        this.setPrepareStatement(preStat, 4, this.sessionContainer.getUserRecordID());
        if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
          this.setPrepareStatement(preStat, 5, oneDayBeforeCurrTime);
          this.setPrepareStatement(preStat, 6, this.sessionContainer.getUserRecordID());
        }
        
        if (searchForm.isSearchable()) {
          String searchKeyword = this.getFormattedKeyword(searchForm.getBasicSearchKeyword(), searchForm.getBasicSearchType());
          if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
            this.setPrepareStatement(preStat, 7, searchKeyword);
          }else{
            this.setPrepareStatement(preStat, 5, searchKeyword);
          }
        }
        
        rs = preStat.executeQuery();
        while (rs.next()) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          result.add(tmpDmsDocument);
        }
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  
  /**
   * Gets the parent document(s) (folder, compound or paper document) under the list of roots specified in the list of 
   * root ID.
   * 
   * <PRE>
   * 
   * Two fields in the ListDmsFolderSelectForm to decide include compound or paper document as result parent document.
   * 1. AllowCompoundDoc - true if the compound document(s) includes as result
   * 2. AllowPaperDoc - true if the paper document(s) includes as result
   * 
   * Basic search can be achieved by, e.g.
   * searchForm.setBasicSearchField("document_name");
   * searchForm.setBasicSearchType("=");
   * searchForm.setBasicSearchKeyword("XXXX.doc"); 
   * 
   * Paging is supported to get the result list.
   * </PRE>
   * @param searchForm the ListDmsFolderSelectForm object
   * @param rootIDs the list of root id 
   * @return list the dmsDocument objects
   * @throws ApplicationException
   * 
   * 
   */
  public synchronized List getDmsFolderListByRootIDLists(AbstractSearchForm searchForm, List rootIDs) throws
  ApplicationException {
    PreparedStatement preStat = null;
    
    PreparedStatement preStatCnt = null;
    ResultSet rs = null;
    ResultSet rsCnt = null;
    StringBuffer sqlStat = new StringBuffer();
    StringBuffer sqlStatCnt = new StringBuffer();
    List result = new ArrayList();
    int totalNumOfRecord = 0;
    int rowLoopCnt = 0;
    int startOffset = TextUtility.parseInteger(searchForm.getCurStartRowNo());
    int pageSize = TextUtility.parseInteger(searchForm.getPageOffset());
    ListDmsDocumentForm docSearchForm = (ListDmsDocumentForm) searchForm;
    Timestamp currTime = Utility.getCurrentTimestamp();
    Timestamp oneDayBeforeCurrTime = Utility.addDay(currTime, -1);
    
    ListDmsFolderSelectForm listFolderSelectForm = (ListDmsFolderSelectForm) docSearchForm;
    String allowCompoundDoc = listFolderSelectForm.getAllowCompoundDoc();
    String allowPaperDoc=listFolderSelectForm.getAllowPaperDoc();
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE,A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF,A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        sqlStat.append("WHERE  A.RECORD_STATUS = ? ");
        if (!Utility.isEmpty(listFolderSelectForm.getDocumentType())) {
          sqlStat.append("       AND (A.DOCUMENT_TYPE=? ");
          if(!"false".equals(allowCompoundDoc)){
            sqlStat.append(" OR A.DOCUMENT_TYPE=? ");
          }
          if(!"false".equals(allowPaperDoc)){
            sqlStat.append(" OR A.DOCUMENT_TYPE=? ");
          }
          sqlStat.append(")");
        }
        sqlStat.append("       AND (((A.EFFECTIVE_START_DATE IS NULL OR A.EFFECTIVE_START_DATE <= ?) ");
        sqlStat.append("       AND (A.EFFECTIVE_END_DATE IS NULL OR A.EFFECTIVE_END_DATE > ?)) ");
        sqlStat.append("       OR A.OWNER_ID = ?) ");
        
        // Form the WHERE clause for filtering.
        /*if (searchForm.isSearchable()) {
         String searchField = searchForm.getBasicSearchField();
         if (searchField.indexOf(".") < 0) {
         searchField = "A." + searchField;
         }
         sqlStat.append("AND  " + searchField + " " + searchForm.getBasicSearchType() + " ? ");
         }*/
        
        if (searchForm.isSearchable()) {
          String searchField = getSearchColumn(searchForm.getBasicSearchField());
          sqlStat.append("AND  " + searchField + " " + searchForm.getBasicSearchType() + " ? ");
        }
        
        if (rootIDs.size() > 0) {
          sqlStat.append(" AND ( ");
          for (int i = 0; i < rootIDs.size(); i++) {
            sqlStat.append(" A.ROOT_ID = ? ");
            if (i + 1 < rootIDs.size()) {
              sqlStat.append(" OR ");
            }
          }
          sqlStat.append(" )  ");
        } else {
          sqlStat.append(" AND A.ROOT_ID = ?   ");
        }
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        // Form the ORDER clause for sorting.
        if (searchForm.isSortable()) {
          String sortAttribute = searchForm.getSortAttribute();
          if (sortAttribute.indexOf(".") < 0) {
            sortAttribute = "A." + sortAttribute;
          }
          sqlStat.append("ORDER BY  " + sortAttribute + " " + searchForm.getSortOrder());
        }
        
        // Get total number of record return.
        sqlStatCnt = this.getSelectCountSQL(sqlStat);
        preStatCnt = dbConn.prepareStatement(sqlStatCnt.toString());
        int i = 0;
        this.setPrepareStatement(preStatCnt, ++i, GlobalConstant.RECORD_STATUS_ACTIVE);
        if (!Utility.isEmpty(listFolderSelectForm.getDocumentType())) {
          this.setPrepareStatement(preStatCnt, ++i, listFolderSelectForm.getDocumentType());
          if(!"false".equals(allowCompoundDoc)){
            this.setPrepareStatement(preStatCnt, ++i, DmsDocument.COMPOUND_DOC_TYPE);
          }
          if(!"false".equals(allowPaperDoc)){
            this.setPrepareStatement(preStatCnt, ++i, DmsDocument.PAPER_DOC_TYPE);
          }
          
        }
        this.setPrepareStatement(preStatCnt, ++i, currTime);
        this.setPrepareStatement(preStatCnt, ++i, oneDayBeforeCurrTime);
        this.setPrepareStatement(preStatCnt, ++i, this.sessionContainer.getUserRecordID());
        if (searchForm.isSearchable()) {
          String searchKeyword = this.getFormattedKeyword(searchForm.getBasicSearchKeyword(), searchForm.getBasicSearchType());
          this.setPrepareStatement(preStatCnt, ++i, searchKeyword);
        }
        if (rootIDs.size() > 0) {
          for (int j = 0; j < rootIDs.size(); j++) {
            Integer rootID = (Integer) rootIDs.get(j);
            log.debug("rooid = " + rootID);
            setPrepareStatement(preStatCnt, ++i, rootID);
          }
        } else {
          setPrepareStatement(preStatCnt, ++i, docSearchForm.getRootID());
          log.debug("rooid = " + docSearchForm.getRootID());
        }
        
        rsCnt = preStatCnt.executeQuery();
        if (rsCnt.next()) {
          totalNumOfRecord = rsCnt.getInt(1);
        }
        try {
          rsCnt.close();
        } catch (Exception ignore) {} finally {
          rsCnt = null;
        }
        try {
          preStatCnt.close();
        } catch (Exception ignore) {} finally {
          preStatCnt = null;
        }
        
        // Retrieve the result in row basis.
        sqlStat = this.getSelectListSQL(sqlStat, startOffset, pageSize);
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        i = 0;
        this.setPrepareStatement(preStat, ++i, GlobalConstant.RECORD_STATUS_ACTIVE);
        if (!Utility.isEmpty(listFolderSelectForm.getDocumentType())) {
          this.setPrepareStatement(preStat, ++i, listFolderSelectForm.getDocumentType());
          if(!"false".equals(allowCompoundDoc)){
            this.setPrepareStatement(preStat, ++i, DmsDocument.COMPOUND_DOC_TYPE);
          }
          if(!"false".equals(allowPaperDoc)){
            this.setPrepareStatement(preStat, ++i, DmsDocument.PAPER_DOC_TYPE);
          }
        }
        this.setPrepareStatement(preStat, ++i, currTime);
        this.setPrepareStatement(preStat, ++i, oneDayBeforeCurrTime);
        this.setPrepareStatement(preStat, ++i, this.sessionContainer.getUserRecordID());
        if (searchForm.isSearchable()) {
          String searchKeyword = this.getFormattedKeyword(searchForm.getBasicSearchKeyword(), searchForm.getBasicSearchType());
          this.setPrepareStatement(preStat, ++i, searchKeyword);
        }
        if (rootIDs.size() > 0) {
          for (int j = 0; j < rootIDs.size(); j++) {
            Integer rootID = (Integer) rootIDs.get(j);
            log.debug("rooid = " + rootID);
            setPrepareStatement(preStat, ++i, rootID);
          }
        } else {
          setPrepareStatement(preStat, ++i, docSearchForm.getRootID());
          log.debug("rooid = " + docSearchForm.getRootID());
        }
        
        rs = preStat.executeQuery();
        
        this.positionCursor(rs, startOffset, pageSize);
        while (rs.next() && rowLoopCnt < pageSize) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          tmpDmsDocument.setRecordCount(totalNumOfRecord);
          tmpDmsDocument.setRowNum(startOffset++);
          ++rowLoopCnt;
          result.add(tmpDmsDocument);
        }
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
        try {
          rsCnt.close();
        } catch (Exception ignore) {} finally {
          rsCnt = null;
        }
        try {
          preStatCnt.close();
        } catch (Exception ignore) {} finally {
          preStatCnt = null;
        }
      }
    }
  }
  
  /**
   * Gets the total number of document(s) under the given root
   * 
   * @param recordStatus Record status of the dmsDocument object(s)
   * @param rootID the root ID
   * @return Integer of the total no. of documents
   * @throws ApplicationException
   */
  public synchronized Integer getNoOfFileUnderRoot(String recordStatus, Integer rootID) throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    Integer result = null;
    
    synchronized (dbConn) {
      try {
        
        sqlStat.append("SELECT COUNT(*)   ");
        sqlStat.append("FROM   DMS_DOCUMENT D ");
        sqlStat.append("WHERE D.DOCUMENT_TYPE<>");
        sqlStat.append("'" + DmsDocument.FOLDER_TYPE + "' ");
        sqlStat.append("AND D.RECORD_STATUS = ? ");
        sqlStat.append("AND D.ROOT_ID = ? ");
        
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, recordStatus);
        this.setPrepareStatement(preStat, 2, rootID);
        rs = preStat.executeQuery();
        if (rs.next()) {
          result = this.getResultSetInteger(rs, 1);
        }
        if (result == null) {
          result = new Integer(0);
        }
        return result;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle);
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  /**
   * Gets the total number of file size under the specified root
   * @param recordStatus the record status of the document for calculating the document size
   * @param rootID the root ID
   * @return Double the total document size in KBytes.
   * @throws ApplicationException
   */
  public synchronized Double getTotalFileSizeUnderRoot(String recordStatus, Integer rootID) throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    Double result = null;
    
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT ((SUM(D.ITEM_SIZE))/1024)   ");
        sqlStat.append("FROM   DMS_DOCUMENT D, DMS_VERSION V ");
        sqlStat.append("WHERE D.ID = V.DOCUMENT_ID ");
        sqlStat.append("AND D.DOCUMENT_TYPE<>");
        sqlStat.append("'" + DmsDocument.FOLDER_TYPE + "' ");
        sqlStat.append("AND D.RECORD_STATUS = ? ");
        sqlStat.append("AND D.ROOT_ID = ? ");
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, recordStatus);
        this.setPrepareStatement(preStat, 2, rootID);
        
        rs = preStat.executeQuery();
        if (rs.next()) {
          result = this.getResultSetDouble(rs, 1);
        }
        if (result == null) {
          result = new Double(0.0);
        }
        return result;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle);
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  /**
   * Gets all the deleted document(s) under the personal folder of the current user
   * 
   * @return List the DmsDocument object
   * @throws ApplicationException
   */
  public synchronized List getAllDeletedPersonalDocumentList() throws ApplicationException{
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    List result = new ArrayList();
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE,A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID,A.EXT_REF, A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        sqlStat.append("WHERE   A.ROOT_ID = ? AND A.RECORD_STATUS = ? AND A.UPDATER_ID = ? ");
        
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        DmsDocument personalDocument = getPersonalRootFolderByCreatorID(sessionContainer.getUserRecordID());
        this.setPrepareStatement(preStat, 1, personalDocument.getRootID());
        this.setPrepareStatement(preStat, 2, GlobalConstant.RECORD_STATUS_INACTIVE);
        this.setPrepareStatement(preStat, 3, this.sessionContainer.getUserRecordID());
        rs = preStat.executeQuery();
        while(rs.next()){
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          result.add(tmpDmsDocument);
          
        }
        return result;
        
      }catch (SQLException sqle){
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle);
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
        
      }
      
    }//end syn
    
  }
  
  /**
   * Gets all the deleted document(s)
   * 
   * @return List of the deleted document
   * @throws ApplicationException
   */
  public synchronized List getAllDeletedDocumentList() throws ApplicationException{
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    List result = new ArrayList();
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE,A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF, A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        sqlStat.append("WHERE  A.RECORD_STATUS = ?  ");
        sqlStat.append("AND A.UPDATER_ID = ? ");
        
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, GlobalConstant.RECORD_STATUS_INACTIVE);
        this.setPrepareStatement(preStat, 2, this.sessionContainer.getUserRecordID());
        
        rs = preStat.executeQuery();
        while(rs.next()){
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          result.add(tmpDmsDocument);
          
        }
        return result;
      }catch (SQLException sqle){
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle);
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }//end finally
      
      
      
    }//end syn
    
    
    
  }//end method
  
  
  /**
   * Gets the all the deleted document for layout listing display
   * <PRE>
   * 
   * Basic search can be achieved by, e.g.
   * searchForm.setBasicSearchField("document_name");
   * searchForm.setBasicSearchType("=");
   * searchForm.setBasicSearchKeyword("XXXX.doc"); 
   * 
   * Paging is supported to get the result list.   
   * 
   * </PRE>
   * @param searchForm the ListDmsDocumentForm object
   * @return List of the deleted object(s)
   * @throws ApplicationException
   */
  public synchronized List getDeletedDocumentList(AbstractSearchForm searchForm) throws ApplicationException {
    PreparedStatement preStat = null;
    
    PreparedStatement preStatCnt = null;
    ResultSet rs = null;
    ResultSet rsCnt = null;
    StringBuffer sqlStat = new StringBuffer();
    StringBuffer sqlStatCnt = new StringBuffer();
    List result = new ArrayList();
    int totalNumOfRecord = 0;
    int rowLoopCnt = 0;
    int startOffset = TextUtility.parseInteger(searchForm.getCurStartRowNo());
    int pageSize = TextUtility.parseInteger(searchForm.getPageOffset());
    ListDmsDocumentForm docSearchForm = (ListDmsDocumentForm) searchForm;
    Timestamp currTime = Utility.getCurrentTimestamp();
    Timestamp oneDayBeforeCurrTime = Utility.addDay(currTime, -1);
    
    boolean flag = false;
    if (sessionContainer != null){
      PermissionManager permissionManager=sessionContainer.getPermissionManager();
      if (permissionManager != null){
        if (Utility.isEmpty(permissionManager.getPersonalPermission())){
          flag = true;
        }
      }
    }
    
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE,A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF,A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        if (flag) {
          sqlStat.append(", DMS_ROOT R ");
        }
        sqlStat.append("WHERE  A.RECORD_STATUS = ?  ");
        
        if (!Utility.isEmpty(docSearchForm.getRootIDAry())) {
//        sqlStat.append("AND A.ROOT_ID IN (" + docSearchForm.getRootIDAry()+ " ) ");
          sqlStat.append("       AND "+getInSQL("A.ROOT_ID", docSearchForm.getRootIDAry()) );
        }else{
          sqlStat.append("AND A.UPDATER_ID = ? ");
        }
        
        if (flag){
          sqlStat.append("AND R.ID = A.ROOT_ID AND R.ROOT_TYPE = ? ");
        }
        
        // Form the WHERE clause for filtering.
        
        if (searchForm.isSearchable()) {
          String searchField = getSearchColumn(searchForm.getBasicSearchField());
          sqlStat.append("AND  " + searchField + " " + searchForm.getBasicSearchType() + " ? ");
        }
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        // Form the ORDER clause for sorting.
        sqlStat.append("ORDER BY A.DOCUMENT_TYPE DESC  ");
        if (searchForm.isSortable()) {
          String sortAttribute = searchForm.getSortAttribute();
          if (sortAttribute.indexOf(".") < 0) {
            sortAttribute = "A." + sortAttribute;
          }
          sqlStat.append(", " + sortAttribute + " " + searchForm.getSortOrder());
        }
        
        // Get total number of record return.
        sqlStatCnt = this.getSelectCountSQL(sqlStat);
        preStatCnt = dbConn.prepareStatement(sqlStatCnt.toString());
        int x=1;
        this.setPrepareStatement(preStatCnt, x++, GlobalConstant.RECORD_STATUS_INACTIVE);
        if (Utility.isEmpty(docSearchForm.getRootIDAry())) {
          this.setPrepareStatement(preStatCnt, x++, this.sessionContainer.getUserRecordID());
        }
        if (flag){
          this.setPrepareStatement(preStatCnt,x++,DmsRoot.PUBLIC_ROOT);
        }
        if (searchForm.isSearchable()) {
          String searchKeyword = this.getFormattedKeyword(searchForm.getBasicSearchKeyword(), searchForm.getBasicSearchType());
          this.setPrepareStatement(preStatCnt, x++, searchKeyword);
        }
        rsCnt = preStatCnt.executeQuery();
        if (rsCnt.next()) {
          totalNumOfRecord = rsCnt.getInt(1);
        }
        try {
          rsCnt.close();
        } catch (Exception ignore) {} finally {
          rsCnt = null;
        }
        try {
          preStatCnt.close();
        } catch (Exception ignore) {} finally {
          preStatCnt = null;
        }
        
        // Retrieve the result in row basis.
        sqlStat = this.getSelectListSQL(sqlStat, startOffset, pageSize);
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        x=1;
        this.setPrepareStatement(preStat, x++, GlobalConstant.RECORD_STATUS_INACTIVE);
        if (Utility.isEmpty(docSearchForm.getRootIDAry())) {
          this.setPrepareStatement(preStat, x++, this.sessionContainer.getUserRecordID());
        }
        if (flag){
          this.setPrepareStatement(preStat,x++,DmsRoot.PUBLIC_ROOT);
        }
        if (searchForm.isSearchable()) {
          String searchKeyword = this.getFormattedKeyword(searchForm.getBasicSearchKeyword(), searchForm.getBasicSearchType());
          this.setPrepareStatement(preStat, x++, searchKeyword);
        }
        rs = preStat.executeQuery();
        
        this.positionCursor(rs, startOffset, pageSize);
        while (rs.next() && rowLoopCnt < pageSize) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          tmpDmsDocument.setRecordCount(totalNumOfRecord);
          tmpDmsDocument.setRowNum(startOffset++);
          ++rowLoopCnt;
          result.add(tmpDmsDocument);
        }
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
        try {
          rsCnt.close();
        } catch (Exception ignore) {} finally {
          rsCnt = null;
        }
        try {
          preStatCnt.close();
        } catch (Exception ignore) {} finally {
          preStatCnt = null;
        }
      }
    }
  }
  
  /**
   * Gets all deleted documetn(s) under the personal folder of the current user for layout listing display
   * 
   * <PRE>
   * 
   * Basic search can be achieved by, e.g.
   * searchForm.setBasicSearchField("document_name");
   * searchForm.setBasicSearchType("=");
   * searchForm.setBasicSearchKeyword("XXXX.doc"); 
   * 
   * 
   * Paging is supported to get the result list.
   * 
   * </PRE>
   * 
   * @param searchForm the ListDmsDocumentForm object
   * @return List of the deleted dmsDocument object
   * @throws ApplicationException
   */
  public synchronized List getDeletedPersonalDocumentList(AbstractSearchForm searchForm) throws ApplicationException {
    PreparedStatement preStat = null;
    
    PreparedStatement preStatCnt = null;
    ResultSet rs = null;
    ResultSet rsCnt = null;
    StringBuffer sqlStat = new StringBuffer();
    StringBuffer sqlStatCnt = new StringBuffer();
    List result = new ArrayList();
    int totalNumOfRecord = 0;
    int rowLoopCnt = 0;
    int startOffset = TextUtility.parseInteger(searchForm.getCurStartRowNo());
    int pageSize = TextUtility.parseInteger(searchForm.getPageOffset());
    ListDmsDocumentForm docSearchForm = (ListDmsDocumentForm) searchForm;
    Timestamp currTime = Utility.getCurrentTimestamp();
    Timestamp oneDayBeforeCurrTime = Utility.addDay(currTime, -1);
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE,A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF,A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        sqlStat.append("WHERE   A.ROOT_ID = ? AND A.RECORD_STATUS = ? AND A.UPDATER_ID = ? ");
        
        // Form the WHERE clause for filtering.
        /*
         if (searchForm.isSearchable()) {
         String searchField = searchForm.getBasicSearchField();
         if (searchField.indexOf(".") < 0) {
         searchField = "A." + searchField;
         }
         sqlStat.append("AND  " + searchField + " " +
         searchForm.getBasicSearchType() + " ? ");
         }*/
        if (searchForm.isSearchable()) {
          String searchField = getSearchColumn(searchForm.getBasicSearchField());
          sqlStat.append("AND  " + searchField + " " + searchForm.getBasicSearchType() + " ? ");
        }
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        // Form the ORDER clause for sorting.
        sqlStat.append("ORDER BY A.DOCUMENT_TYPE DESC  ");
        if (searchForm.isSortable()) {
          String sortAttribute = searchForm.getSortAttribute();
          if (sortAttribute.indexOf(".") < 0) {
            sortAttribute = "A." + sortAttribute;
          }
          sqlStat.append(", " + sortAttribute + " " + searchForm.getSortOrder());
        }
        
        // Get total number of record return.
        sqlStatCnt = this.getSelectCountSQL(sqlStat);
        preStatCnt = dbConn.prepareStatement(sqlStatCnt.toString());
        int x=1;
        DmsDocument personalDocument = getPersonalRootFolderByCreatorID(sessionContainer.getUserRecordID());
        this.setPrepareStatement(preStatCnt, x++, personalDocument.getRootID());
        this.setPrepareStatement(preStatCnt, x++, GlobalConstant.RECORD_STATUS_INACTIVE);
        this.setPrepareStatement(preStatCnt, x++, this.sessionContainer.getUserRecordID());
        if (searchForm.isSearchable()) {
          String searchKeyword = this.getFormattedKeyword(searchForm.getBasicSearchKeyword(), searchForm.getBasicSearchType());
          this.setPrepareStatement(preStatCnt, x++, searchKeyword);
        }
        rsCnt = preStatCnt.executeQuery();
        if (rsCnt.next()) {
          totalNumOfRecord = rsCnt.getInt(1);
        }
        try {
          rsCnt.close();
        } catch (Exception ignore) {} finally {
          rsCnt = null;
        }
        try {
          preStatCnt.close();
        } catch (Exception ignore) {} finally {
          preStatCnt = null;
        }
        
        // Retrieve the result in row basis.
        sqlStat = this.getSelectListSQL(sqlStat, startOffset, pageSize);
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        x=1;
        this.setPrepareStatement(preStat, x++, personalDocument.getRootID());
        this.setPrepareStatement(preStat, x++, GlobalConstant.RECORD_STATUS_INACTIVE);
        this.setPrepareStatement(preStat, x++, this.sessionContainer.getUserRecordID());
        if (searchForm.isSearchable()) {
          String searchKeyword = this.getFormattedKeyword(searchForm.getBasicSearchKeyword(), searchForm.getBasicSearchType());
          this.setPrepareStatement(preStat, x++, searchKeyword);
        }
        rs = preStat.executeQuery();
        
        this.positionCursor(rs, startOffset, pageSize);
        while (rs.next() && rowLoopCnt < pageSize) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          tmpDmsDocument.setRecordCount(totalNumOfRecord);
          tmpDmsDocument.setRowNum(startOffset++);
          ++rowLoopCnt;
          result.add(tmpDmsDocument);
        }
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
        try {
          rsCnt.close();
        } catch (Exception ignore) {} finally {
          rsCnt = null;
        }
        try {
          preStatCnt.close();
        } catch (Exception ignore) {} finally {
          preStatCnt = null;
        }
      }
    }
  }
  
  /**
   * Gets all the active document(s) in the DMS
   * 
   * @return list of the DmsDocument object(s)
   * @throws ApplicationException
   */
  public synchronized List getAllDocumentList() throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    List result = new ArrayList();
    Timestamp currTime = Utility.getCurrentTimestamp();
    Timestamp oneDayBeforeCurrTime = Utility.addDay(currTime, -1);
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE, A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF, A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        sqlStat.append("WHERE  A.RECORD_STATUS = ? ");
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, GlobalConstant.RECORD_STATUS_ACTIVE);
        
        rs = preStat.executeQuery();
        while (rs.next()) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          result.add(tmpDmsDocument);
        }
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  /**
   * Gets all the doucment in the DMS include active and inactive document(s)
   * 
   * @return list of the DmsDocument object
   * @throws ApplicationException
   */
  public synchronized List getAllDocumentListActiveInactive() throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    List result = new ArrayList();
    Timestamp currTime = Utility.getCurrentTimestamp();
    Timestamp oneDayBeforeCurrTime = Utility.addDay(currTime, -1);
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE, A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF ,A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        
        rs = preStat.executeQuery();
        while (rs.next()) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          result.add(tmpDmsDocument);
        }
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  /**
   * Gets the document(s) under the specified root and with specified document type
   * 
   * @param rootID the root Id
   * @param documentType the document Type
   * @return List of the DmsDocument object
   * @throws ApplicationException
   */
  public synchronized List getListByRootID(Integer rootID, String documentType) throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    List result = new ArrayList();
    Timestamp currTime = Utility.getCurrentTimestamp();
    Timestamp oneDayBeforeCurrTime = Utility.addDay(currTime, -1);
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE, A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF,A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        sqlStat.append("WHERE  (A.RECORD_STATUS = ? OR A.RECORD_STATUS = ?)  ");
        if (rootID != null) {
          sqlStat.append("AND A.ROOT_ID = ? ");
        }
        sqlStat.append("       AND (((A.EFFECTIVE_START_DATE IS NULL OR A.EFFECTIVE_START_DATE <= ?) ");
        sqlStat.append("       AND (A.EFFECTIVE_END_DATE IS NULL OR A.EFFECTIVE_END_DATE > ?)) ");
        sqlStat.append("       OR A.OWNER_ID = ?) ");
        if (!"*".equals(documentType)) {
          sqlStat.append("AND A.DOCUMENT_TYPE = ? ");
        }
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        sqlStat.append("ORDER BY A.DOCUMENT_TYPE ASC, A.DOCUMENT_NAME ASC ");
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        int i = 0;
        this.setPrepareStatement(preStat, ++i, GlobalConstant.RECORD_STATUS_ACTIVE);
        this.setPrepareStatement(preStat, ++i, GlobalConstant.RECORD_STATUS_PENDING);
        //this.setPrepareStatement(preStat, ++i, parentID);
        if (rootID != null) {
          this.setPrepareStatement(preStat, ++i, rootID);
        }
        
        this.setPrepareStatement(preStat, ++i, currTime);
        this.setPrepareStatement(preStat, ++i, oneDayBeforeCurrTime);
        this.setPrepareStatement(preStat, ++i, this.sessionContainer.getUserRecordID());
        if (!"*".equals(documentType)) {
          this.setPrepareStatement(preStat, ++i, documentType);
        }
        rs = preStat.executeQuery();
        while (rs.next()) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          result.add(tmpDmsDocument);
        }
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  /**
   * Gets the DmsDocument object by given document id and record status.
   * 
   * @param id the DmsDocument object ID 
   * @param recordStatus the document record status
   * @return
   * @throws ApplicationException
   */
  public synchronized AbstractBaseObject getByIDRecordStatus(Integer id, String recordStatus) throws ApplicationException {
    return this.getByID(id, recordStatus);
  }
  
  /**
   * Get Personal Root Folder By Createor ID.
   * 
   * @param creatorID the creator ID (User record ID)
   * @return The DmsDocument Object
   * @throws ApplicationException
   */
  public synchronized DmsDocument getPersonalRootFolderByCreatorID(Integer creatorID) throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    DmsDocument tmpDmsDocument = new DmsDocument();
    Integer parentID = new Integer(0);
    
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE,A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF,A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
//      sqlStat.append("WHERE  A.PARENT_ID = ? AND A.CREATOR_ID = ? AND A.RECORD_STATUS = ? ");
        sqlStat.append("WHERE  A.PARENT_ID = ? AND A.OWNER_ID = ? AND A.RECORD_STATUS = ? ");
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        //this.setPrepareStatement(preStat, 1, name);
        this.setPrepareStatement(preStat, 1, parentID);
        this.setPrepareStatement(preStat, 2, creatorID);
        this.setPrepareStatement(preStat, 3, GlobalConstant.RECORD_STATUS_ACTIVE);
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        rs = preStat.executeQuery();
        
        if (rs.next()) {
          tmpDmsDocument = parseObjectFromResultSet(rs);
          return (tmpDmsDocument);
        } else {
          return (null);
        }
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  /**
   * get document list ,and the document with the document's version list.
   * <PRE>
   * only the document type and compound document type document are get.
   * 
   * 
   * Basic search can be achieved by, e.g.
   * searchForm.setBasicSearchField("document_name");
   * searchForm.setBasicSearchType("=");
   * searchForm.setBasicSearchKeyword("XXXX.doc"); 
   * 
   * 
   * Paging is supported to get the result list.
   * 
   * </PRE>
   * @param searchForm the ListDmsDocumentForm object
   * @return List of the DmsDocument object
   * @throws ApplicationException
   */
  public synchronized List getDocumentWithVersionLabelList(AbstractSearchForm searchForm) throws ApplicationException {
    PreparedStatement preStat = null;
    PreparedStatement preStatCnt = null;
    ResultSet rs = null;
    ResultSet rsCnt = null;
    StringBuffer sqlStat = new StringBuffer();
    StringBuffer sqlStatCnt = new StringBuffer();
    List result = new ArrayList();
    int totalNumOfRecord = 0;
    int rowLoopCnt = 0;
    int startOffset = TextUtility.parseInteger(searchForm.getCurStartRowNo());
    int pageSize = TextUtility.parseInteger(searchForm.getPageOffset());
    ListDmsDocumentForm docSearchForm = (ListDmsDocumentForm) searchForm;
    Timestamp currTime = Utility.getCurrentTimestamp();
    Timestamp oneDayBeforeCurrTime = Utility.addDay(currTime, -1);
    
    DmsVersionDAObject dmsVersionDAO = new DmsVersionDAObject(sessionContainer, dbConn);
    
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE,A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF,A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        sqlStat.append("WHERE  A.RECORD_STATUS = ? AND ( A.DOCUMENT_TYPE = ? OR A.DOCUMENT_TYPE = ? OR A.DOCUMENT_TYPE=? OR A.DOCUMENT_TYPE=? OR A.DOCUMENT_TYPE=? OR A.DOCUMENT_TYPE=?) AND A.ROOT_ID = ? AND A.PARENT_ID = ? ");
        sqlStat.append("       AND (((A.EFFECTIVE_START_DATE IS NULL OR A.EFFECTIVE_START_DATE <= ?) ");
        sqlStat.append("       AND (A.EFFECTIVE_END_DATE IS NULL OR A.EFFECTIVE_END_DATE > ?)) ");
        sqlStat.append("       OR A.OWNER_ID = ?) ");
        
        // Form the WHERE clause for filtering.
        /*
         if (searchForm.isSearchable()) {
         String searchField = searchForm.getBasicSearchField();
         if (searchField.indexOf(".") < 0) {
         searchField = "A." + searchField;
         }
         sqlStat.append("AND  " + searchField + " " + searchForm.getBasicSearchType() + " ? ");
         }*/
        
        if (searchForm.isSearchable()) {
          String searchField = getSearchColumn(searchForm.getBasicSearchField());
          sqlStat.append("AND  " + searchField + " " + searchForm.getBasicSearchType() + " ? ");
        }
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        // Form the ORDER clause for sorting.
        sqlStat.append("ORDER BY A.DOCUMENT_TYPE DESC  ");
        if (searchForm.isSortable()) {
          String sortAttribute = searchForm.getSortAttribute();
          if (sortAttribute.indexOf(".") < 0) {
            sortAttribute = "A." + sortAttribute;
          }
          sqlStat.append(", " + sortAttribute + " " + searchForm.getSortOrder());
        }
        
        // Get total number of record return.
        sqlStatCnt = this.getSelectCountSQL(sqlStat);
        preStatCnt = dbConn.prepareStatement(sqlStatCnt.toString());
        
        this.setPrepareStatement(preStatCnt, 1, GlobalConstant.RECORD_STATUS_ACTIVE);
        this.setPrepareStatement(preStatCnt, 2, DmsDocument.DOCUMENT_TYPE);
        this.setPrepareStatement(preStatCnt, 3, DmsDocument.COMPOUND_DOC_TYPE);
        this.setPrepareStatement(preStatCnt, 4, DmsDocument.PAPER_DOC_TYPE);
        this.setPrepareStatement(preStatCnt, 5, DmsDocument.EMAIL_DOC_TYPE);
        this.setPrepareStatement(preStatCnt, 6, DmsDocument.FORM_DOC_TYPE);
        this.setPrepareStatement(preStatCnt, 7, DmsDocument.FLOW_DOC_TYPE);
        this.setPrepareStatement(preStatCnt, 8, docSearchForm.getRootID());
        this.setPrepareStatement(preStatCnt, 9, docSearchForm.getParentID());
        this.setPrepareStatement(preStatCnt, 10, currTime);
        this.setPrepareStatement(preStatCnt, 11, oneDayBeforeCurrTime);
        this.setPrepareStatement(preStatCnt, 12, this.sessionContainer.getUserRecordID());
        
        if (searchForm.isSearchable()) {
          String searchKeyword = this.getFormattedKeyword(searchForm.getBasicSearchKeyword(), searchForm.getBasicSearchType());
          this.setPrepareStatement(preStatCnt, 13, searchKeyword);
        }
        rsCnt = preStatCnt.executeQuery();
        if (rsCnt.next()) {
          totalNumOfRecord = rsCnt.getInt(1);
        }
        try {
          rsCnt.close();
        } catch (Exception ignore) {} finally {
          rsCnt = null;
        }
        try {
          preStatCnt.close();
        } catch (Exception ignore) {} finally {
          preStatCnt = null;
        }
        
        // Retrieve the result in row basis.
        sqlStat = this.getSelectListSQL(sqlStat, startOffset, pageSize);
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, GlobalConstant.RECORD_STATUS_ACTIVE);
        this.setPrepareStatement(preStat, 2, DmsDocument.DOCUMENT_TYPE);
        this.setPrepareStatement(preStat, 3, DmsDocument.COMPOUND_DOC_TYPE);
        this.setPrepareStatement(preStat, 4, DmsDocument.PAPER_DOC_TYPE);
        this.setPrepareStatement(preStat, 5, DmsDocument.EMAIL_DOC_TYPE);
        this.setPrepareStatement(preStat, 6, DmsDocument.FORM_DOC_TYPE);
        this.setPrepareStatement(preStat, 7, DmsDocument.FLOW_DOC_TYPE);
        this.setPrepareStatement(preStat, 8, docSearchForm.getRootID());
        this.setPrepareStatement(preStat, 9, docSearchForm.getParentID());
        this.setPrepareStatement(preStat, 10, currTime);
        this.setPrepareStatement(preStat, 11, oneDayBeforeCurrTime);
        this.setPrepareStatement(preStat, 12, this.sessionContainer.getUserRecordID());
        
        if (searchForm.isSearchable()) {
          String searchKeyword = this.getFormattedKeyword(searchForm.getBasicSearchKeyword(), searchForm.getBasicSearchType());
          this.setPrepareStatement(preStat, 13, searchKeyword);
        }
        rs = preStat.executeQuery();
        this.positionCursor(rs, startOffset, pageSize);
        
        while (rs.next() && rowLoopCnt < pageSize) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          tmpDmsDocument.setRecordCount(totalNumOfRecord);
          tmpDmsDocument.setRowNum(startOffset++);
          
          //get the document's version list
          List tmpVersionList = dmsVersionDAO.getVersionsListByDocumentID(getResultSetInteger(rs, "ID"), " ");
          tmpDmsDocument.setDmsVersionList(tmpVersionList);
          ++rowLoopCnt;
          result.add(tmpDmsDocument);
        }
        
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
        try {
          rsCnt.close();
        } catch (Exception ignore) {} finally {
          rsCnt = null;
        }
        try {
          preStatCnt.close();
        } catch (Exception ignore) {} finally {
          preStatCnt = null;
        }
      }
    }
  }
  
  /**
   * Delete the record in the table DMS_DOCUMENT with the given ID i.e. Hard delete
   * 
   * @param obj The DmsDocument object
   * @throws ApplicationException
   */
  public synchronized void hardDelete(AbstractBaseObject obj) throws ApplicationException {
    
    PreparedStatement preStat = null;
    StringBuffer sqlStat = new StringBuffer();
    DmsDocument tmpDmsDocument = (DmsDocument) ( (DmsDocument) obj).clone();
    
    synchronized (dbConn) {
      try {
        int updateCnt = 0;
        sqlStat.append("DELETE ");
        sqlStat.append("FROM   DMS_DOCUMENT ");
        sqlStat.append("WHERE  ID=?  ");
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        setPrepareStatement(preStat, 1, tmpDmsDocument.getID());
        
        updateCnt = preStat.executeUpdate();
        
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_DELETE_ERROR, e);
      } finally {
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  /**
   * Gets the DmsDocument object which is deleted with given DmsDocument object ID
   * 
   * @param id the DmsDocument object
   * @return the deleted DmsDocument object
   * @throws ApplicationException
   */
  public synchronized AbstractBaseObject getInactiveByID(Integer id) throws
  ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE, A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF,A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        //sqlStat.append("WHERE  A.ID = ? AND A.RECORD_STATUS = ? ");
        sqlStat.append("WHERE  A.ID = ?  ");
        sqlStat.append("AND RECORD_STATUS=?  ");
        
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, id);
        this.setPrepareStatement(preStat, 2, GlobalConstant.RECORD_STATUS_INACTIVE);
        
        rs = preStat.executeQuery();
        if (rs.next()) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          return (tmpDmsDocument);
        } else {
          return null;
        }
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  
  /**
   * Gets the list of the DmsDocument object(s) with the given document profile detail ID.
   * 
   * @param udfDetailID the document profiel detail ID
   * @return list of the DmsDocument object 
   * @throws ApplicationException
   * @see com.dcivision.dms.bean.DmsDocumentDetail
   */
  public synchronized List getDocumentListByUdfDetailID(Integer udfDetailID) throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    List result = new ArrayList();
    
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE, A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF, A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10,DD.USER_DEFINED_FIELD_ID ,A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A , DMS_DOCUMENT_DETAIL DD ");
        sqlStat.append("WHERE  A.RECORD_STATUS = ? ");
        sqlStat.append("AND A.ID = DD.DOCUMENT_ID ");
        sqlStat.append("AND DD.USER_DEFINED_FIELD_DETAIL_ID = ? ");
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, GlobalConstant.RECORD_STATUS_ACTIVE);
        this.setPrepareStatement(preStat, 2, udfDetailID);
        rs = preStat.executeQuery();
        while (rs.next()) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          result.add(tmpDmsDocument);
        }
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  /**
   * Checks whether a document is exists with the document with specified document ID.
   * 
   * @param docID the DmsDocument object ID
   * @return true if the document exist
   * @throws ApplicationException
   */
  public synchronized boolean checkDocExist(Integer docID) throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    boolean docExist = false;
    
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        sqlStat.append("WHERE  A.ID = ? ");
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, docID);
        
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        rs = preStat.executeQuery();
        
        if (rs.next()) {
          docExist = true;
        } else {
          docExist = false;
        }
        return docExist;
        
      }catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle,
            sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  /**
   * Gets the all the document(s) (document, compound or paper document) that not archived under the specified folder.
   * 
   * @param parentID the DmsDocument object ID of the folder
   * @return List of the DmsDocument object(s)
   * @throws ApplicationException
   */
  public synchronized List getListForArchive(Integer parentID) throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    List result = new ArrayList();
    
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE, A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF, A.EXT_REF, A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10 ,A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        sqlStat.append("WHERE  A.RECORD_STATUS = ? AND A.PARENT_ID = ? AND ( A.DOCUMENT_TYPE = ? OR A.DOCUMENT_TYPE = ? OR A.DOCUMENT_TYPE = ? ) AND A.ITEM_STATUS <> ? ");
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        preStat = dbConn.prepareStatement(sqlStat.toString());
        this.setPrepareStatement(preStat, 1, GlobalConstant.RECORD_STATUS_ACTIVE);
        this.setPrepareStatement(preStat, 2, parentID);
        this.setPrepareStatement(preStat, 3, DmsDocument.DOCUMENT_TYPE);
        this.setPrepareStatement(preStat, 4, DmsDocument.COMPOUND_DOC_TYPE);
        this.setPrepareStatement(preStat, 5, DmsDocument.PAPER_DOC_TYPE);
        this.setPrepareStatement(preStat, 6, "R");
        rs = preStat.executeQuery();
        while (rs.next()) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          result.add(tmpDmsDocument);
        }
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
//Override the mothed getCriteriaCombinationMySQL()
  protected HashMap getCriteriaCombinationMySQL(String sFieldName, String sFieldValue, boolean bExactMatch) {
    HashMap mResult = new HashMap();
    List fieldResult = new ArrayList();
    List criteria = new ArrayList();
    String sResult = " ( ";
    
    boolean bOR  = false;
    boolean bAND = false;
    boolean bNewOR  = false;
    boolean bNewAND = false;
    String bLIKEPRO = "";
    boolean bRangeSearch = false;
    String delim = "";
    int exists = 0;
    
    StringTokenizer st = new StringTokenizer(sFieldValue);
    String tmpCriteria = "";
    while (st.hasMoreTokens()) {
      String str = st.nextToken().trim();
      
      if ("OR".equals(str)) {
        bOR = true;
        delim = "OR";
        criteria.add(new String(tmpCriteria));
        tmpCriteria = "";
        str="";
      }
      else if("||".equals(str)){
        bNewOR=true;
        delim = "OR";
        criteria.add(new String(tmpCriteria));
        tmpCriteria = "";
        str="";
      }
      else if("&&".equals(str)){
        bNewAND=true;
        delim = "AND";
        criteria.add(new String(tmpCriteria));
        tmpCriteria = "";
        str="";
      }
      else if ("AND".equals(str)) {
        bAND = true;
        delim = "AND";
        criteria.add(new String(tmpCriteria));
        tmpCriteria = "";
        str="";
      }
      else if (">".equals(str)) {
        bRangeSearch = true;
        delim = ">";
        criteria.add(new String(tmpCriteria));
        tmpCriteria = "";
        str="";
      }
      else if (">=".equals(str)) {
        bRangeSearch = true;
        delim = ">=";
        criteria.add(new String(tmpCriteria));
        tmpCriteria = "";
        str="";
      }
      if (!Utility.isEmpty(str)) {
        tmpCriteria = tmpCriteria + " " + str;
      }
      
    }
    if (!Utility.isEmpty(tmpCriteria)) {
      criteria.add(new String(tmpCriteria));
    }
    log.debug("delim = " + delim);
    
    //For range search
    if (bRangeSearch == true){
      String minValue = "";
      String maxValue = "";
      //while (st.hasMoreTokens()) {
      for (int i = 0; i<criteria.size(); i ++) {
        if (Utility.isEmpty(minValue)){
          minValue = getExactMatchKeyword((String)criteria.get(i), bExactMatch);
          minValue = minValue.replaceFirst("%", "");
          if(!bExactMatch){
            if((!Utility.isEmpty(minValue))&&(minValue.lastIndexOf("%")==(minValue.length()-1))){
              minValue=minValue.substring(0,minValue.length()-1);
            }
          }
          fieldResult.add(minValue);
        }else{
          maxValue = getExactMatchKeyword((String)criteria.get(i), bExactMatch);
          maxValue = maxValue.replaceFirst("%", "");
          if(!bExactMatch){
            if((!Utility.isEmpty(maxValue))&&(maxValue.lastIndexOf("%")==(maxValue.length()-1))){
              maxValue=maxValue.substring(0,maxValue.length()-1);
            }
          }
          fieldResult.add(maxValue);
        }
        exists++;
      }
      if (">".equals(delim)) {
        sResult = sResult + sFieldName + " > ? AND " + sFieldName + " < ? ";
      }
      else if (">=".equals(delim)) {
        sResult = sResult + sFieldName + " >= ? AND " + sFieldName + " <= ? ";
      }
    }//No Range search, only the comnibation of AND/OR
    else if (bAND==true || bOR ==true || bNewAND==true || bNewOR==true){
      //while (st.hasMoreTokens()) {
      for (int i = 0; i<criteria.size(); i ++) {
        String value = getExactMatchKeyword((String)criteria.get(i), bExactMatch);
        value=TextUtility.replaceString(value,"*","%");
        log.debug("value is:"+value);
        String tmpStr = "";
        String sEqual = "=";
        if (value.indexOf("NOT") >= 0) {
          bLIKEPRO=" NOT LIKE ";
          value = value.replaceAll("NOT ", "").trim();
          value = value.replaceAll("%", "").trim();
          sEqual = "!=";
        }else{
          bLIKEPRO=" LIKE ";
        }
        fieldResult.add(value);
        
        if (bExactMatch == false) {
          tmpStr = sFieldName + bLIKEPRO + " ? ";
        }else{
          tmpStr = sFieldName + " " + sEqual + " ? ";
        }
        
        if (i!=0) {
          tmpStr =  " " + delim + " " + tmpStr;
        }
        
        
        sResult = sResult + tmpStr;
        exists++;
      }
    }//One keyword only
    else {
      
      String value = getExactMatchKeyword(tmpCriteria, bExactMatch);
      String tmpStr = "";
      String sEquals="=";
      if (value.indexOf("NOT") >= 0) {
        bLIKEPRO=" NOT LIKE ";
        value = value.replaceAll("NOT ", "").trim();
        value = value.replaceAll("%", "").trim();
        sEquals = "!=";
      }else{
        bLIKEPRO=" LIKE ";
      }
      value=TextUtility.replaceString(value,"*","%");
      fieldResult.add(value);
      if (bExactMatch == false) {
        
        tmpStr = sFieldName + bLIKEPRO + " ? ";
      }
      else {
        tmpStr = sFieldName + " " + sEquals + " ? " ;
      }
      sResult = sResult + tmpStr;
      exists++;
      
    }
    
    sResult = sResult+" ) ";
    mResult.put("SQL", sResult);
    mResult.put("?", TextUtility.formatInteger(exists));
    mResult.put("fieldResult", fieldResult);
    return mResult;
  }
  
  /**
   * Gets all the active document(s) with the given parent ID and root ID specifid in the properties of the searchForm object
   * <PRE>
   *
   * Basic search can be achieved by, e.g.
   * searchForm.setBasicSearchField("document_name");
   * searchForm.setBasicSearchType("=");
   * searchForm.setBasicSearchKeyword("XXXX.doc"); 
   * 
   * Paging is supported to get the result list. 
   * 
   * </PRE>
   * @param searchForm the ListDmsDocumentForm object 
   * @return list of the DmsDocument object(s)
   * @throws ApplicationException
   */
  public synchronized List getDocumentListDocFolder(AbstractSearchForm searchForm) throws ApplicationException {
    PreparedStatement preStat = null;
    PreparedStatement preStatCnt = null;
    ResultSet rs = null;
    ResultSet rsCnt = null;
    StringBuffer sqlStat = new StringBuffer();
    StringBuffer sqlStatCnt = new StringBuffer();
    List result = new ArrayList();
    int totalNumOfRecord = 0;
    int rowLoopCnt = 0;
    int startOffset = TextUtility.parseInteger(searchForm.getCurStartRowNo());
    int pageSize = TextUtility.parseInteger(searchForm.getPageOffset());
    ListDmsDocumentForm docSearchForm = (ListDmsDocumentForm) searchForm;
    Timestamp currTime = Utility.getCurrentTimestamp();
    Timestamp oneDayBeforeCurrTime = Utility.addDay(currTime, -1);
    
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE,A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF, A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        sqlStat.append("WHERE  A.RECORD_STATUS = ?  AND A.ROOT_ID = ? AND A.PARENT_ID = ? ");
        sqlStat.append("       AND (((A.EFFECTIVE_START_DATE IS NULL OR A.EFFECTIVE_START_DATE <= ?) ");
        sqlStat.append("       AND (A.EFFECTIVE_END_DATE IS NULL OR A.EFFECTIVE_END_DATE > ?)) ");
        sqlStat.append("       OR A.OWNER_ID = ?) ");
        
        
        // Form the WHERE clause for filtering.
        /*
         if (searchForm.isSearchable()) {
         String searchField = searchForm.getBasicSearchField();
         if (searchField.indexOf(".") < 0) {
         searchField = "A." + searchField;
         }
         sqlStat.append("AND  " + searchField + " " + searchForm.getBasicSearchType() + " ? ");
         }*/
        
        if (searchForm.isSearchable()) {
          String searchField = getSearchColumn(searchForm.getBasicSearchField());
          sqlStat.append("AND  " + searchField + " " + searchForm.getBasicSearchType() + " ? ");
        }
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        // Form the ORDER clause for sorting.
        sqlStat.append("ORDER BY A.DOCUMENT_TYPE DESC  ");
        if (searchForm.isSortable()) {
          String sortAttribute = searchForm.getSortAttribute();
          if (sortAttribute.indexOf(".") < 0) {
            sortAttribute = "A." + sortAttribute;
          }
          sqlStat.append(", " + sortAttribute + " " + searchForm.getSortOrder());
        }
        
        // Get total number of record return.
        sqlStatCnt = this.getSelectCountSQL(sqlStat);
        preStatCnt = dbConn.prepareStatement(sqlStatCnt.toString());
        this.setPrepareStatement(preStatCnt, 1, GlobalConstant.RECORD_STATUS_ACTIVE);
        this.setPrepareStatement(preStatCnt, 2, docSearchForm.getRootID());
        this.setPrepareStatement(preStatCnt, 3, docSearchForm.getParentID());
        this.setPrepareStatement(preStatCnt, 4, currTime);
        
        
        this.setPrepareStatement(preStatCnt, 5, oneDayBeforeCurrTime);
        this.setPrepareStatement(preStatCnt, 6, this.sessionContainer.getUserRecordID());
        
        
        if (searchForm.isSearchable()) {
          String searchKeyword = this.getFormattedKeyword(searchForm.getBasicSearchKeyword(), searchForm.getBasicSearchType());
          this.setPrepareStatement(preStatCnt, 7, searchKeyword);
        }
        rsCnt = preStatCnt.executeQuery();
        if (rsCnt.next()) {
          totalNumOfRecord = rsCnt.getInt(1);
        }
        try {
          rsCnt.close();
        } catch (Exception ignore) {} finally {
          rsCnt = null;
        }
        try {
          preStatCnt.close();
        } catch (Exception ignore) {} finally {
          preStatCnt = null;
        }
        
        // Retrieve the result in row basis.
        sqlStat = this.getSelectListSQL(sqlStat, startOffset, pageSize);
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, GlobalConstant.RECORD_STATUS_ACTIVE);
        this.setPrepareStatement(preStat, 2, docSearchForm.getRootID());
        this.setPrepareStatement(preStat, 3, docSearchForm.getParentID());
        this.setPrepareStatement(preStat, 4, currTime);
        
        
        this.setPrepareStatement(preStat, 5, oneDayBeforeCurrTime);
        this.setPrepareStatement(preStat, 6, this.sessionContainer.getUserRecordID());
        
        
        if (searchForm.isSearchable()) {
          String searchKeyword = this.getFormattedKeyword(searchForm.getBasicSearchKeyword(), searchForm.getBasicSearchType());
          this.setPrepareStatement(preStat, 7, searchKeyword);
        }
        rs = preStat.executeQuery();
        this.positionCursor(rs, startOffset, pageSize);
        
        while (rs.next() && rowLoopCnt < pageSize) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          tmpDmsDocument.setRecordCount(totalNumOfRecord);
          tmpDmsDocument.setRowNum(startOffset++);
          ++rowLoopCnt;
          result.add(tmpDmsDocument);
        }
        
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
        try {
          rsCnt.close();
        } catch (Exception ignore) {} finally {
          rsCnt = null;
        }
        try {
          preStatCnt.close();
        } catch (Exception ignore) {} finally {
          preStatCnt = null;
        }
      }
    }
  }
  
  /**
   * Delete all the marked deleted record in the table DMS_DOCUMENT.
   * 
   * @throws ApplicationException
   */
  public synchronized void deleteAllInactiveRecord() throws ApplicationException {
    
    PreparedStatement preStat = null;
    StringBuffer sqlStat = new StringBuffer();
    synchronized (dbConn) {
      try {
        int updateCnt = 0;
        sqlStat.append("DELETE ");
        sqlStat.append("FROM   DMS_DOCUMENT ");
        sqlStat.append("WHERE RECORD_STATUS =? AND OWNER_ID = ?");
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        setPrepareStatement(preStat, 1, GlobalConstant.RECORD_STATUS_INACTIVE);
        setPrepareStatement(preStat, 2, this.getSessionContainer().getUserRecordID());
        updateCnt = preStat.executeUpdate();
        
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_DELETE_ERROR, e);
      } finally {
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  
  
  /**
   * Gets the document(s) with given parent ID, root ID, document type or a set of document ID
   * <P>
   * For view public folder function access.
   * </P>
   * 
   * @param parentID the DmsDocument object parent ID
   * @param rootID the DmsDocument object root ID
   * @param documentType the document type
   * @param docIDStr the string of the set of the document ID with "," delimiter e.g. "1001,1002,1003"
   
   * @return list the DmsDocument object
   * @throws ApplicationException
   */
  
  public synchronized List getListByParentID(Integer parentID, Integer rootID, String documentType ,String docIDStr ) throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    List result = new ArrayList();
    Timestamp currTime = Utility.getCurrentTimestamp();
    Timestamp oneDayBeforeCurrTime = Utility.addDay(currTime, -1);
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE, A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF, A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        sqlStat.append("WHERE  (A.RECORD_STATUS = ? OR A.RECORD_STATUS = ?) AND A.PARENT_ID = ?   ");
        if (rootID != null) {
          sqlStat.append("AND A.ROOT_ID = ? ");
        }
        
        if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
          sqlStat.append("      AND (((A.EFFECTIVE_START_DATE IS NULL OR A.EFFECTIVE_START_DATE <=?) ");
          sqlStat.append("      AND (A.EFFECTIVE_END_DATE IS NULL OR A.EFFECTIVE_END_DATE >?)) ");
          sqlStat.append("      OR A.OWNER_ID = ?) ");
        }
        
        if (!"*".equals(documentType)) {
          sqlStat.append("AND (A.DOCUMENT_TYPE = ? OR A.DOCUMENT_TYPE = '" + DmsDocument.COMPOUND_DOC_TYPE + "' OR A.DOCUMENT_TYPE='"+DmsDocument.PAPER_DOC_TYPE+"' ) ");
        }
        
        if(!"".equals(docIDStr)){
//        sqlStat.append("AND A.ID in ("+docIDStr+")  ");
          sqlStat.append("       AND "+getInSQL("A.ID", docIDStr) );
        }
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        sqlStat.append("ORDER BY A.DOCUMENT_TYPE ASC, A.DOCUMENT_NAME ASC ");
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        int i = 0;
        this.setPrepareStatement(preStat, ++i, GlobalConstant.RECORD_STATUS_ACTIVE);
        this.setPrepareStatement(preStat, ++i, GlobalConstant.RECORD_STATUS_PENDING);
        this.setPrepareStatement(preStat, ++i, parentID);
        if (rootID != null) {
          this.setPrepareStatement(preStat, ++i, rootID);
        }
        
        if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
          this.setPrepareStatement(preStat, ++i, currTime);
          this.setPrepareStatement(preStat, ++i, oneDayBeforeCurrTime);
          this.setPrepareStatement(preStat, ++i, this.sessionContainer.getUserRecordID());
        }
        
        if (!"*".equals(documentType)) {
          this.setPrepareStatement(preStat, ++i, documentType);
        }
        rs = preStat.executeQuery();
        while (rs.next()) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          result.add(tmpDmsDocument);
        }
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  /**
   * Gets the active document(s) with the same document name of the given.
   * 
   * @param documentName the document name
   * @return list of the DmsDocument object
   * @throws ApplicationException
   */
  public synchronized List getListByDocumentName(String documentName) throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    List result = new ArrayList();
    Timestamp currTime = Utility.getCurrentTimestamp();
    Timestamp oneDayBeforeCurrTime = Utility.addDay(currTime, -1);
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE, A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF, A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        sqlStat.append("WHERE  A.RECORD_STATUS = ? ");
        sqlStat.append("       AND (((A.EFFECTIVE_START_DATE IS NULL OR A.EFFECTIVE_START_DATE <= ?) ");
        sqlStat.append("       AND (A.EFFECTIVE_END_DATE IS NULL OR A.EFFECTIVE_END_DATE > ?)) ");
        sqlStat.append("       OR A.OWNER_ID = ?) ");
        sqlStat.append("       AND A.DOCUMENT_NAME = ?");
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, GlobalConstant.RECORD_STATUS_ACTIVE);
        this.setPrepareStatement(preStat, 2, currTime);
        this.setPrepareStatement(preStat, 3, oneDayBeforeCurrTime);
        this.setPrepareStatement(preStat, 4, this.sessionContainer.getUserRecordID());
        this.setPrepareStatement(preStat, 5, documentName);             
        
        rs = preStat.executeQuery();
        while (rs.next()) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          result.add(tmpDmsDocument);
        }
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  /**
   * Gets the active document by the given document type and the reference no 
   * 
   * @param documentType the document type
   * @param referenceNo the reference no.
   * @return the DmsDocument object
   * @throws ApplicationException
   */
  public synchronized DmsDocument getDocumentByDocTypeRefNo(String documentType, String referenceNo) throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    DmsDocument tmpDmsDocument = new DmsDocument();
    
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE,A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF, A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        sqlStat.append("WHERE  A.DOCUMENT_TYPE = ? AND A.REFERENCE_NO = ? AND A.RECORD_STATUS = ? ");
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, documentType);
        this.setPrepareStatement(preStat, 2, referenceNo);
        this.setPrepareStatement(preStat, 3, GlobalConstant.RECORD_STATUS_ACTIVE);
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        rs = preStat.executeQuery();
        
        if (rs.next()) {
          tmpDmsDocument = parseObjectFromResultSet(rs);
          return (tmpDmsDocument);
        } else {
          return (null);
        }
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle,
            sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  /**
   * Gets all active document type (DmsDocuemnt.DOCUMENT_TYPE) document.
   * 
   * @return list of the DmsDocument object
   * @throws ApplicationException
   */
  public synchronized List getAllDocumentUDFList() throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    List result = new ArrayList();
    Timestamp currTime = Utility.getCurrentTimestamp();
    Timestamp oneDayBeforeCurrTime = Utility.addDay(currTime, -1);
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE, A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF, A.EXT_REF, A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        sqlStat.append("WHERE  A.RECORD_STATUS = ? ");
        sqlStat.append("AND A.DOCUMENT_TYPE = ?");
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, GlobalConstant.RECORD_STATUS_ACTIVE);
        this.setPrepareStatement(preStat,2,GlobalConstant.OBJECT_TYPE_DOCUMENT);
        rs = preStat.executeQuery();
        while (rs.next()) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          result.add(tmpDmsDocument);
        }
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  
  /**
   * Gets the document profile information by the given DmsDocument object and a set of version
   *
   * @param docObject the dmsDocument object 
   * @param string of version id in format i.e. "1001,1002,1003"
   * @return the list of document profile information
   * <PRE>
   * 
   * The items of the list contains:
   * First item:      A String array which store 
   *                     [Doc Name][Num of Version][Cur Version][Doc Type]
   * Following items: A String array which store  
   *                     [Profile Name][Field Name][Field Value]
   * 
   * </PRE>
   * @throws ApplicationException
   * <pre>
   * 
   *            ApplicationException with the following message codes will be thrown
   *            ErrorConstant.ErrorConstant.DB_GENERAL_ERROR - General caught SQLException
   *            ErrorConstant.DB_SELECT_ERROR - All kind of caught Exception
   *  
   * </pre>
   */
  public synchronized List getDocumentProfileInfo(DmsDocument docObject,String versinIDStr) throws ApplicationException {
    List result = new ArrayList();
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    PreparedStatement preStat2 = null;
    ResultSet rs2 = null;
    StringBuffer sqlStat2 = new StringBuffer();
    PreparedStatement preStat3 = null;
    ResultSet rs3 = null;
    PreparedStatement preStat4 = null;
    ResultSet rs4 = null;
    PreparedStatement preStat5 = null;
    ResultSet rs5 = null;
    PreparedStatement preStat6 = null;
    ResultSet rs6 = null;
    
    synchronized (dbConn) {
      try {
        // Get the document name and document type.
        String documentName = "";
        String documentType = "";
        String numOfVersion = "";
        StringBuffer curVersion = new StringBuffer();
        if (Utility.isEmpty(docObject.getDocumentType())) {
          sqlStat.append("SELECT A.DOCUMENT_NAME, A.DOCUMENT_TYPE ");
          sqlStat.append("FROM   DMS_DOCUMENT A ");
          sqlStat.append("WHERE  A.ID = ? ");
          
          //format the sql for any 'LIKE' statement contained
          sqlStat = this.getFormattedSQL(sqlStat.toString());
          
          preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
          this.setPrepareStatement(preStat, 1, docObject.getID());
          
          rs = preStat.executeQuery();
          if (rs.next()) {
            documentName = rs.getString(1);
            documentType = rs.getString(2);
          } else {
            throw new ApplicationException(ErrorConstant.DB_RECORD_NOT_FOUND_ERROR);
          }
          
        } else {
          documentName = docObject.getDocumentName();
          documentType = docObject.getDocumentType();
        }
        
        // Get the no. of version.
        sqlStat = new StringBuffer();
        sqlStat.append("SELECT COUNT(*) ");
        sqlStat.append("FROM   DMS_VERSION A ");
        sqlStat.append("WHERE  A.DOCUMENT_ID = ? ");
        preStat3 = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat3, 1, docObject.getID());
        rs3 = preStat3.executeQuery();
        if (rs3.next()) {
          numOfVersion = rs3.getString(1);
        }
        
        //get lastest version object
        String curVersionID = "";
        String curDocumentVersionID = "";
        sqlStat = new StringBuffer();
        sqlStat.append("SELECT MAX(A.ID) ");
        sqlStat.append("FROM   DMS_VERSION A ");
        sqlStat.append("WHERE  A.DOCUMENT_ID = ? ");
        preStat4 = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat4, 1, docObject.getID());
        rs4 = preStat4.executeQuery();
        if (rs4.next()) {
          curVersionID = rs4.getString(1);
        }
        
        //if input a versinIDStr then use this versionID
        if(!Utility.isEmpty(versinIDStr) && !DmsOperationConstant.DMS_TOP_VERSION.equals(versinIDStr) ){
          curVersionID = versinIDStr;
        }
        
        // Get the cur major version
        sqlStat = new StringBuffer();
        String parentID = "";
        String refrenceNo = "";
        String description = "";
        sqlStat.append("SELECT A.VERSION_NUMBER, A.PARENT_ID , A.REFERENCE_NO , A.DESCRIPTION ");
        sqlStat.append("FROM   DMS_VERSION A ");
        sqlStat.append("WHERE  ID = ? ");
        preStat5 = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat5, 1, curVersionID);
        rs5 = preStat5.executeQuery();
        if (rs5.next()) {
          curDocumentVersionID = rs5.getString(1);
          refrenceNo = rs5.getString(3);
          description = rs5.getString(4);
        }
        curVersion.append(curDocumentVersionID);
        
        // Add the first row. [Doc Name][Num of Version][Cur Version][Doc Type]
        result.add(new String[] {documentName, numOfVersion.toString(), curVersion.toString(), documentType ,refrenceNo,description});
        
        sqlStat = new StringBuffer();
        sqlStat.append("SELECT DISTINCT A.USER_DEFINED_TYPE, A.ID ");
        sqlStat.append("FROM   SYS_USER_DEFINED_INDEX A, DMS_DOCUMENT_DETAIL B ");
        sqlStat.append("WHERE  B.DOCUMENT_ID = ? AND A.ID = B.USER_DEFINED_FIELD_ID ");
        preStat6 = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat6, 1, docObject.getID());
        rs6 = preStat6.executeQuery();

        sqlStat2.append("SELECT B.FIELD_NAME, A.FIELD_VALUE, A.DATE_VALUE, A.NUMERIC_VALUE, B.FIELD_TYPE ");
        sqlStat2.append("FROM   DMS_DOCUMENT_DETAIL A, SYS_USER_DEFINED_INDEX_DETAIL B ");
        sqlStat2.append("WHERE  A.DOCUMENT_ID = ? AND B.ID = A.USER_DEFINED_FIELD_DETAIL_ID AND A.USER_DEFINED_FIELD_ID = ? ");
        sqlStat2.append("ORDER BY B.DISPLAY_SEQ , A.USER_DEFINED_FIELD_DETAIL_ID ASC");
        
        try {
          while (rs6.next()) {
            preStat2 = dbConn.prepareStatement(sqlStat2.toString());
            this.setPrepareStatement(preStat2, 1, docObject.getID());
            this.setPrepareStatement(preStat2, 2, new Integer(rs6.getInt(2)));
            rs2 = preStat2.executeQuery();
            String profileName = rs6.getString(1);
            String fieldName = "";
            String fieldValue = "";
            
            while (rs2.next()) {
              // Add the follow rows. [Profile Name][Field Name][Field Value]
              fieldName = rs2.getString(1);
              String tmpStr2 = rs2.getString(2);
              Timestamp tmpStr3 = rs2.getTimestamp(3);
              String tmpStr4 = rs2.getString(4);
              String tmpStr5 = rs2.getString(5);
              
              if (SysUserDefinedIndexDetail.DATE_FIELD.equals(tmpStr5)) {
                fieldValue = TextUtility.formatTimestampToDate(tmpStr3);
              } else if (SysUserDefinedIndexDetail.NUMBER_FIELD.equals(tmpStr5)) {
                fieldValue = tmpStr4;
              } else {
                fieldValue = tmpStr2;
              }
              result.add(new String[] {profileName, fieldName, fieldValue});
            }
            if (!Utility.isEmpty(profileName) && Utility.isEmpty(fieldName)) {
              result.add(new String[] {profileName, fieldName, fieldValue});
            }
          }
        } catch (SQLException sqle) {
          log.error(sqle, sqle);
          throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
        } catch (Exception e) {
          log.error(e, e);
          throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
        } finally {
        }
        
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {  
        DbUtils.closeQuietly(rs);
        DbUtils.closeQuietly(preStat);
        DbUtils.closeQuietly(rs2);
        DbUtils.closeQuietly(preStat2);
        DbUtils.closeQuietly(rs3);
        DbUtils.closeQuietly(preStat3);
        DbUtils.closeQuietly(rs4);
        DbUtils.closeQuietly(preStat4);
        DbUtils.closeQuietly(rs5);
        DbUtils.closeQuietly(preStat5);
        DbUtils.closeQuietly(rs6);
        DbUtils.closeQuietly(preStat6);
      }
    }
  }
  
  public synchronized List getFolderListByParentID(Integer parentID, Integer rootID, String documentType, boolean getReferenceFile) throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    List result = new ArrayList();
    Timestamp currTime = Utility.getCurrentTimestamp();
    Timestamp oneDayBeforeCurrTime = Utility.addDay(currTime, -1);
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE, A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF, A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        sqlStat.append("WHERE  (A.RECORD_STATUS = ? OR A.RECORD_STATUS = ? ");
        
        if(getReferenceFile){
          sqlStat.append(" OR A.RECORD_STATUS = ? " );
        }
        
        
        sqlStat.append(" ) AND A.PARENT_ID = ?   ");
        if (rootID != null) {
          sqlStat.append("AND A.ROOT_ID = ? ");
        }
        
        if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
          sqlStat.append("      AND (((A.EFFECTIVE_START_DATE IS NULL OR A.EFFECTIVE_START_DATE <=?) ");
          sqlStat.append("      AND (A.EFFECTIVE_END_DATE IS NULL OR A.EFFECTIVE_END_DATE >?)) ");
          sqlStat.append("      OR A.OWNER_ID = ?) ");
        }
        
        if (!"*".equals(documentType)) {
          sqlStat.append("AND (A.DOCUMENT_TYPE = ? OR A.DOCUMENT_TYPE = '" + "' ) ");
        }
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        sqlStat.append("ORDER BY A.DOCUMENT_TYPE ASC, A.DOCUMENT_NAME ASC ");
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        int i = 0;
        this.setPrepareStatement(preStat, ++i, GlobalConstant.RECORD_STATUS_ACTIVE);
        this.setPrepareStatement(preStat, ++i, GlobalConstant.RECORD_STATUS_PENDING);
        
        if(getReferenceFile){
          this.setPrepareStatement(preStat, ++i, DmsOperationConstant.DMS_RECORD_EMPTY);
        }
        
        this.setPrepareStatement(preStat, ++i, parentID);
        if (rootID != null) {
          this.setPrepareStatement(preStat, ++i, rootID);
        }
        
        if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
          this.setPrepareStatement(preStat, ++i, currTime);
          this.setPrepareStatement(preStat, ++i, oneDayBeforeCurrTime);
          this.setPrepareStatement(preStat, ++i, this.sessionContainer.getUserRecordID());
        }
        
        if (!"*".equals(documentType)) {
          this.setPrepareStatement(preStat, ++i, documentType);
        }
        rs = preStat.executeQuery();
        while (rs.next()) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          result.add(tmpDmsDocument);
        }
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  /**
   * Advance Search Ignore Duplic Shortcut
   * 
   * @param searchForm  the ListDmsDocumentForm object
   * @param rootIDs the list of the root ID to limit the searched document under the given root
   * @param documentIDs the step 1 return's documentID str
   * @param runSeq      the run seq number ,step 1 runSeq value = 1 ,step2 runSeq value = 2 
   * @return List the document(s) matched the search criteria 
   * @throws ApplicationException
   * <PRE>
   * To get the ignored duplic shortcut,need to do 2 step,the step 1 is get all not duplic shortcut result's doc id,
   * step2 is get the step1 return's doc id 's document 
   * 
   * </PRE>
   */
  public synchronized List getAdvanceSearchDocumentIDListIgnoreDuplicShortcut (AbstractSearchForm searchForm, List rootIDs , String documentIDs,int runSeq) throws ApplicationException {
    PreparedStatement preStat = null;
    PreparedStatement preStatCnt = null;
    ResultSet rs = null;
    ResultSet rsCnt = null;
    StringBuffer sqlStat = new StringBuffer();
    StringBuffer sqlStatCnt = new StringBuffer();
    List result = new ArrayList();
    List tempResult = new ArrayList();    
    int totalNumOfRecord = 0;
    int rowLoopCnt = 0;
    int startOffset = TextUtility.parseInteger(searchForm.getCurStartRowNo());
    int pageSize = TextUtility.parseInteger(searchForm.getPageOffset());
    
    ListDmsDocumentForm docSearchForm = (ListDmsDocumentForm) searchForm;
    List docDetailList = docSearchForm.getDocumentDetails();
    HashMap mFieldMap = new HashMap();
    
    Timestamp currTime = Utility.getCurrentTimestamp();
    Timestamp oneDayBeforeCurrTime = Utility.addDay(currTime, -1);
    DocumentRetrievalManager docRetrievalManager = new DocumentRetrievalManager(sessionContainer, dbConn);
    //Default profile display.
    int totalFieldCount = Integer.parseInt(com.dcivision.framework.SystemParameterFactory.getSystemParameter(com.dcivision.framework.SystemParameterConstant.DMS_DEFAULT_PROFILE_FIELD_COUNT));
    
    synchronized (dbConn) {
      try {
        //SQL
        sqlStat.append("SELECT DISTINCT D.ID, ");
        sqlStat.append("D.DOCUMENT_NAME, D.DOCUMENT_TYPE, D.PARENT_ID, D.ROOT_ID, D.PRIORITY, D.CREATE_TYPE, D.EFFECTIVE_START_DATE, D.EFFECTIVE_END_DATE, D.REMINDER_AMOUNT, D.REMINDER_TYPE, D.NOTIFICATION_WAY, D.OWNER_ID, D.REFERENCE_NO, D.DESCRIPTION, D.ITEM_SIZE, D.ITEM_STATUS, D.CHECKOUT_ID, D.ALERT_EDIT_ID, D.ALERT_INVITE_ID, D.EXT_REF, D.USER_DEF_1, D.USER_DEF_2, D.USER_DEF_3, D.USER_DEF_4, D.USER_DEF_5, D.USER_DEF_6, D.USER_DEF_7, D.USER_DEF_8, D.USER_DEF_9, D.USER_DEF_10, D.RECORD_STATUS, D.UPDATE_COUNT, D.CREATOR_ID, D.CREATE_DATE, D.UPDATER_ID, D.UPDATE_DATE ");
        
        // let join  MTM_DOCUMENT_RELATIONSHIP to get the shot cut sourceid
        if (runSeq == 1) {
          sqlStat.append(",MDR.DOCUMENT_ID AS SOURCE_DOC_ID ");
        }
        
        if (!Utility.isEmpty(docSearchForm.getUserDefinedFieldID())) {
          sqlStat.append(", DI.USER_DEFINED_FIELD_ID ");
        }
        
        sqlStat.append("FROM  ");
//      table1 LEFT JOIN table2 ON table1.id=table2.id
        if (!Utility.isEmpty(docSearchForm.getUserDefinedFieldID())) {
          
          sqlStat.append(" DMS_DOCUMENT D LEFT JOIN DMS_DOCUMENT_INDEX DI ON D.ID=DI.DOCUMENT_ID ");
        } else {
          
          sqlStat.append(" DMS_DOCUMENT D ");
        }
        // let join  MTM_DOCUMENT_RELATIONSHIP to get the shot cut sourceid
        
        sqlStat.append(" LEFT JOIN MTM_DOCUMENT_RELATIONSHIP MDR ON D.ID = MDR.RELATED_DOCUMENT_ID ");
        
        
        sqlStat.append("WHERE  D.RECORD_STATUS = ? ");
        
        //1129
        sqlStat.append(" AND ((D.EFFECTIVE_START_DATE IS NULL OR D.EFFECTIVE_START_DATE <= '" + currTime + "') OR D.OWNER_ID = '" + sessionContainer.getUserRecordID() + "') ");
        
        // TIF_ANNOTATION_TYPE / ORIGINSLITY_EMAIL_TYPE should no display in result list(EIP-1296 lee 07/01/18)
        sqlStat.append(" AND D.DOCUMENT_TYPE <> '"+DmsDocument.TIF_ANNOTATION_TYPE+"' ");
        sqlStat.append(" AND D.DOCUMENT_TYPE <> '"+DmsDocument.ORIGINSLITY_EMAIL_TYPE+"' ");
        
        if(!Utility.isEmpty(documentIDs)){
          sqlStat.append("       AND "+getInSQL("D.ID", documentIDs) );
        }
        
        //to ensure no root folder is selected
        sqlStat.append(" AND D.PARENT_ID <> 0 ");
        
        int tmpCounter = 0; //purpose in checking the WHERE statment
        
        // if (!Utility.isEmpty(docSearchForm.getUserDefinedFieldID())) {
        //   sqlStat.append(" AND D.ID = DI.DOCUMENT_ID");
        // }
        
        sqlStat.append("  AND (");
        
        int startPos = sqlStat.length(); //used to record the criteria
        String outerCriteria = "";
        if (DmsOperationConstant.ATTR_NEST_FILTER_OPERATION.equals(docSearchForm.getOpMode()) &&
            !Utility.isEmpty(docSearchForm.getOuterCriteria())) {
          outerCriteria = docSearchForm.getOuterCriteria();
          
        } else if (DmsOperationConstant.ATTR_EXPORT_OPERATION.equals(docSearchForm.getOpMode()) ||
            DmsOperationConstant.ATTR_COMBINE_TIFF_OPERATION.equals(docSearchForm.getOpMode())) {
          if (DmsOperationConstant.ATTR_NEST_FILTER_OPERATION.equals(docSearchForm.getPrvOpMode()) &&
              !Utility.isEmpty(docSearchForm.getOuterCriteria())) {
            outerCriteria = docSearchForm.getOuterCriteria();
          }
        }
        
        int repe = 0;
        String relationDocumentName="";
        String name="";
        DmsRelationalWord dmsRelationalWord=new DmsRelationalWord();
        String tmp[] = null;
        String sName=TextUtility.convert(docSearchForm.getDocumentName());//convert big5 to gb or gb to big5
        String documentName=docSearchForm.getDocumentName();
        DmsRelationalWordDAObject dmsRelationalWordDaobject = new DmsRelationalWordDAObject(sessionContainer, dbConn);
        //relational word is false or true
        boolean isRelationWord = SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_RELATIONAL_WORD_ENABLE);
        name=docSearchForm.getDocumentName();
        if (!Utility.isEmpty(docSearchForm.getDocumentName())) {
          
          HashMap mResult=null;
          tmpCounter++;
          if(!TextUtility.checkContainsOperandChar(docSearchForm.getDocumentName())){
            name=sName + " OR " +documentName;
            if(isRelationWord){//relatioanal word
              List relationalDocumentNameList = dmsRelationalWordDaobject.getRelationalWordListByKeyWord(docSearchForm.getDocumentName());
              for(int i=0;i<relationalDocumentNameList.size();i++){
                dmsRelationalWord = (DmsRelationalWord)relationalDocumentNameList.get(i);
                relationDocumentName = dmsRelationalWord.getWord();
                name += " OR " + TextUtility.convert(relationDocumentName) + " OR " +relationDocumentName ;
              }
            }
          }
          
          mResult = getCriteriaCombination("D.DOCUMENT_NAME",
              name,
              docSearchForm.getDocumentNameExactMatch());
          
          
          
          sqlStat.append(mResult.get("SQL"));
          
          repe += TextUtility.parseInteger( (String) mResult.get("?"));
          mFieldMap.put("DOCUMENT_NAME",mResult.get("fieldResult"));
          
        }
        
        
        //the personal folder should not be shown in the search case
        
        if (!Utility.isEmpty(docSearchForm.getEffectiveStartDate()) ||
            !Utility.isEmpty(docSearchForm.getEffectiveEndDate())) {
          tmpCounter++;
          if (tmpCounter > 1) {
            sqlStat.append(" " + docSearchForm.getEffectiveDateOption() + " ");
          }
          
          if (DataSourceFactory.getDatabaseType() == DataSourceFactory.DB_ORACLE) {
            
            if ( (!Utility.isEmpty(docSearchForm.getEffectiveStartDate())) &&
                (!Utility.isEmpty(docSearchForm.getEffectiveEndDate()))) {
              sqlStat.append(" (D.EFFECTIVE_START_DATE < = TO_DATE('" + TextUtility.dbDateAdder(docSearchForm.getEffectiveEndDate(), 1) + "','"+ "YYYY-MM-DD HH24:MI:SS" +"') AND D.EFFECTIVE_END_DATE > TO_DATE('" + docSearchForm.getEffectiveStartDate() +
                  "','" + "YYYY-MM-DD HH24:MI:SS" +"')) ");
            } else if ( (!Utility.isEmpty(docSearchForm.getEffectiveStartDate())) && //only first value entered
                (Utility.isEmpty(docSearchForm.getEffectiveEndDate()))) {
              sqlStat.append(" (D.EFFECTIVE_START_DATE >= TO_DATE('" + docSearchForm.getEffectiveStartDate() + "','"+"YYYY-MM-DD HH24:MI:SS"+"' )) ");
            } else if ( (Utility.isEmpty(docSearchForm.getEffectiveStartDate())) && //only 2nd value entered
                (!Utility.isEmpty(docSearchForm.getEffectiveEndDate()))) {
              sqlStat.append(" (D.EFFECTIVE_END_DATE < TO_DATE('" + TextUtility.dbDateAdder(docSearchForm.getEffectiveEndDate(), 1) + "','"+"YYYY-MM-DD HH24:MI:SS"+"' )) ");
            }
          }else{
            if ( (!Utility.isEmpty(docSearchForm.getEffectiveStartDate())) &&
                (!Utility.isEmpty(docSearchForm.getEffectiveEndDate()))) {
              sqlStat.append(" (D.EFFECTIVE_START_DATE < '" + TextUtility.dbDateAdder(docSearchForm.getEffectiveEndDate(), 1) + "' AND D.EFFECTIVE_END_DATE > '" + docSearchForm.getEffectiveStartDate() +
              "' ) ");
            } else if ( (!Utility.isEmpty(docSearchForm.getEffectiveStartDate())) && //only first value entered
                (Utility.isEmpty(docSearchForm.getEffectiveEndDate()))) {
              sqlStat.append(" (D.EFFECTIVE_START_DATE >= '" + docSearchForm.getEffectiveStartDate() + "' ) ");
            } else if ( (Utility.isEmpty(docSearchForm.getEffectiveStartDate())) && //only 2nd value entered
                (!Utility.isEmpty(docSearchForm.getEffectiveEndDate()))) {
              sqlStat.append(" (D.EFFECTIVE_END_DATE < '" + TextUtility.dbDateAdder(docSearchForm.getEffectiveEndDate(), 1) + "' ) ");
            }
          }
          //personal folder will not shown as result
          Integer userID = sessionContainer.getUserRecordID();
          DmsRootDAObject rootDAO = new DmsRootDAObject(sessionContainer, dbConn);
          List rootList = rootDAO.getRootByOwnerIDAndType(userID, DmsRoot.PERSONAL_ROOT, GlobalConstant.RECORD_STATUS_ACTIVE);
          DmsRoot rootPoint = null;
          if (!Utility.isEmpty(rootList)) {
            rootPoint = (DmsRoot) rootList.get(0);
            sqlStat.append(" AND (D.ROOT_ID <>" + rootPoint.getID() + ") ");
          }
        }
        
        //search document by the create date and update date
        
        if (!Utility.isEmpty(docSearchForm.getCreateDate()) ||
            !Utility.isEmpty(docSearchForm.getCreateToDate())) {
          tmpCounter++;
          
          if (tmpCounter > 1) {
            sqlStat.append(" " + docSearchForm.getCreateDateOption() + " ");
          }
          
          if (DataSourceFactory.getDatabaseType() == DataSourceFactory.DB_ORACLE) {
            if ( (!Utility.isEmpty(docSearchForm.getCreateDate())) && (!Utility.isEmpty(docSearchForm.getCreateToDate()))) {
              sqlStat.append(" (D.CREATE_DATE >= TO_DATE('" + docSearchForm.getCreateDate() + "','"+ "YYYY-MM-DD HH24:MI:SS" +"') AND D.CREATE_DATE < TO_DATE('" + TextUtility.dbDateAdder(docSearchForm.getCreateToDate(), 1) + "','" + "YYYY-MM-DD HH24:MI:SS" +"')) ");
            } else if ( (!Utility.isEmpty(docSearchForm.getCreateDate())) && (Utility.isEmpty(docSearchForm.getCreateToDate()))) {
              sqlStat.append(" (D.CREATE_DATE >= TO_DATE('" + docSearchForm.getCreateDate() + "','"+"YYYY-MM-DD HH24:MI:SS"+"')) ");
            } else if ( (Utility.isEmpty(docSearchForm.getCreateDate())) && (!Utility.isEmpty(docSearchForm.getCreateToDate()))) {
              sqlStat.append(" (D.CREATE_DATE < TO_DATE('" + TextUtility.dbDateAdder(docSearchForm.getCreateToDate(), 1) + "','"+"YYYY-MM-DD HH24:MI:SS"+"')) ");
            }
          }else{
            if ( (!Utility.isEmpty(docSearchForm.getCreateDate())) && (!Utility.isEmpty(docSearchForm.getCreateToDate()))) {
              sqlStat.append(" (D.CREATE_DATE >= '" + docSearchForm.getCreateDate() + "' AND D.CREATE_DATE < '" + TextUtility.dbDateAdder(docSearchForm.getCreateToDate(), 1) + "') ");
            } else if ( (!Utility.isEmpty(docSearchForm.getCreateDate())) && (Utility.isEmpty(docSearchForm.getCreateToDate()))) {
              sqlStat.append(" (D.CREATE_DATE >= '" + docSearchForm.getCreateDate() + "') ");
            } else if ( (Utility.isEmpty(docSearchForm.getCreateDate())) && (!Utility.isEmpty(docSearchForm.getCreateToDate()))) {
              sqlStat.append(" (D.CREATE_DATE < '" + TextUtility.dbDateAdder(docSearchForm.getCreateToDate(), 1) + "') ");
            }
            
            
          }
          
        }
        
        if (!Utility.isEmpty(docSearchForm.getUpdateDate()) ||
            !Utility.isEmpty(docSearchForm.getUpdateToDate())) {
          tmpCounter++;
          
          if (tmpCounter > 1) {
            sqlStat.append(" " + docSearchForm.getUpdateDateOption() + " ");
          }
          
          if (DataSourceFactory.getDatabaseType() == DataSourceFactory.DB_ORACLE) {
            if ( (!Utility.isEmpty(docSearchForm.getUpdateDate())) && (!Utility.isEmpty(docSearchForm.getUpdateToDate()))) {
              sqlStat.append(" (D.UPDATE_DATE >= TO_DATE('" + docSearchForm.getUpdateDate() + "','"+ "YYYY-MM-DD HH24:MI:SS" + "') AND D.UPDATE_DATE < TO_DATE('" + TextUtility.dbDateAdder(docSearchForm.getUpdateToDate(), 1) + "','"+"YYYY-MM-DD HH24:MI:SS"+"')) ");
            } else if ( (!Utility.isEmpty(docSearchForm.getUpdateDate())) && (Utility.isEmpty(docSearchForm.getUpdateToDate()))) {
              sqlStat.append(" (D.UPDATE_DATE >= TO_DATE('" + docSearchForm.getUpdateDate() + "','"+ "YYYY-MM-DD HH24:MI:SS" +"')) ");
            } else if ( (Utility.isEmpty(docSearchForm.getUpdateDate())) && (!Utility.isEmpty(docSearchForm.getUpdateToDate()))) {
              sqlStat.append(" (D.UPDATE_DATE < TO_DATE('" + TextUtility.dbDateAdder(docSearchForm.getUpdateToDate(), 1) + "','"+ "YYYY-MM-DD HH24:MI:SS"+"')) ");
            }
          }else{
            if ( (!Utility.isEmpty(docSearchForm.getUpdateDate())) && (!Utility.isEmpty(docSearchForm.getUpdateToDate()))) {
              sqlStat.append(" (D.UPDATE_DATE >= '" + docSearchForm.getUpdateDate() + "' AND D.UPDATE_DATE < '" + TextUtility.dbDateAdder(docSearchForm.getUpdateToDate(), 1) + "') ");
            } else if ( (!Utility.isEmpty(docSearchForm.getUpdateDate())) && (Utility.isEmpty(docSearchForm.getUpdateToDate()))) {
              sqlStat.append(" (D.UPDATE_DATE >= '" + docSearchForm.getUpdateDate() + "') ");
            } else if ( (Utility.isEmpty(docSearchForm.getUpdateDate())) && (!Utility.isEmpty(docSearchForm.getUpdateToDate()))) {
              sqlStat.append(" (D.UPDATE_DATE < '" + TextUtility.dbDateAdder(docSearchForm.getUpdateToDate(), 1) + "') ");
            }
          }
          
        }
        
        if (!Utility.isEmpty(docSearchForm.getDocumentType())) {
          tmpCounter++;
          if (tmpCounter > 1) {
            sqlStat.append(" " + docSearchForm.getDocumentTypeOption() + " ");
          }
          HashMap mResult = getCriteriaCombination("D.DOCUMENT_TYPE",
              docSearchForm.getDocumentType(),
              true);
          sqlStat.append(mResult.get("SQL"));
          repe += TextUtility.parseInteger( (String) mResult.get("?"));
          mFieldMap.put("DOCUMENT_TYPE", mResult.get("fieldResult"));
        }
        
        if (!Utility.isEmpty(docSearchForm.getSearchPriority())) {
          tmpCounter++;
          if (tmpCounter > 1) {
            sqlStat.append(" " + docSearchForm.getPriorityOption() + " ");
          }
          HashMap mResult = getCriteriaCombination("D.PRIORITY",
              Utility.genericLogicSql(docSearchForm.getSearchPriority(),"OR"),
              true);
          sqlStat.append(mResult.get("SQL"));
          repe += TextUtility.parseInteger( (String) mResult.get("?"));
          mFieldMap.put("PRIORITY", mResult.get("fieldResult"));
          
        }
        
        if (!Utility.isEmpty(docSearchForm.getReferenceNo())) {
          tmpCounter++;
          if (tmpCounter > 1) {
            sqlStat.append(" " + docSearchForm.getReferenceNoOption() + " ");
          }
          HashMap mResult = getCriteriaCombination("D.REFERENCE_NO",
              docSearchForm.getReferenceNo(),
              docSearchForm.getReferenceNoExactMatch());
          sqlStat.append(mResult.get("SQL"));
          repe += TextUtility.parseInteger( (String) mResult.get("?"));
          mFieldMap.put("REFERENCE_NO", mResult.get("fieldResult"));
        }
        
        if (!Utility.isEmpty(docSearchForm.getDescription())) {
          
          String sDescription=TextUtility.convert(docSearchForm.getDescription());//convert big5 to gb or gb to big5
          String description=docSearchForm.getDescription();
          String nDescription=description;
          tmpCounter++;
          
          
          
          if (tmpCounter > 1) {
            sqlStat.append(" " + docSearchForm.getDescriptionOption() + " ");
          }
          
          if(!TextUtility.checkContainsOperandChar(docSearchForm.getDescription())){
            nDescription=sDescription + " OR " + description;
            
            if(isRelationWord){//relatioanal word
              List relationalDescriptionList = dmsRelationalWordDaobject.getRelationalWordListByKeyWord(docSearchForm.getDescription());
              for(int i=0;i<relationalDescriptionList.size();i++){
                dmsRelationalWord = (DmsRelationalWord)relationalDescriptionList.get(i);
                String relationDescription = dmsRelationalWord.getWord();
                nDescription += " OR " + TextUtility.convert(relationDescription) + " OR " +relationDescription ;
              }
            }
          }
          
          HashMap mResult = getCriteriaCombination("D.DESCRIPTION",
              nDescription,
              docSearchForm.getDescriptionExactMatch());
          sqlStat.append(mResult.get("SQL"));
          repe += TextUtility.parseInteger( (String) mResult.get("?"));
          mFieldMap.put("DESCRIPTION", mResult.get("fieldResult"));
        }
        
        if (!Utility.isEmpty(docSearchForm.getCreatorID())) {
          tmpCounter++;
          if (tmpCounter > 1) {
            sqlStat.append(" " + docSearchForm.getCreatorOption() + " ");
          }
          HashMap mResult = getCriteriaCombination("D.CREATOR_ID",
              docSearchForm.getCreatorID(),
              true);
          sqlStat.append(mResult.get("SQL"));
          repe += TextUtility.parseInteger( (String) mResult.get("?"));
          mFieldMap.put("CREATOR_ID", mResult.get("fieldResult"));
        }
        
        //iterate userDef1 to userDef10 using reflection
        for(int udfIdx = 1 ; udfIdx<=totalFieldCount ; udfIdx++){
          Class cls = Class.forName(ListDmsDocumentForm.class.getName());
          Method userDefMethod = cls.getMethod("getUserDef"+udfIdx,null);
          String userDefFrom = (String)userDefMethod.invoke(docSearchForm, null);
          Method userDefToMethod = cls.getMethod("getUserDef"+udfIdx+"To",null);
          String userDefTo = (String)userDefToMethod.invoke(docSearchForm, null);
          Method userDefOptionMethod = cls.getMethod("getUserDef"+udfIdx+"Option",null);
          String userDefOption = (String)userDefOptionMethod.invoke(docSearchForm, null);
          
          Method userDefDataTypeMethod = cls.getMethod("getUserDef"+udfIdx+"DataType",null);
          String userDefDataType = (String)userDefDataTypeMethod.invoke(docSearchForm, null);
          
          Method userDefExactMatchMethod = cls.getMethod("getUserDef"+udfIdx+"ExactMatch",null);
          
          boolean userDefExactMatch = ((Boolean)userDefExactMatchMethod.invoke(docSearchForm, null)).booleanValue();         
          if ( (!Utility.isEmpty(userDefFrom)) || (!Utility.isEmpty(userDefTo))) {
            tmpCounter++;
            if (tmpCounter > 1) {
              sqlStat.append(" " + userDefOption + " ");
            }
            
            if (DmsDefaultProfileSetting.FIELD_TYPE_DATE.equals(userDefDataType)) {
              if ( (!Utility.isEmpty(userDefFrom)) && (!Utility.isEmpty(userDefTo))) {
                sqlStat.append(" (D.USER_DEF_" + udfIdx + " >= '" + userDefFrom + "' AND D.USER_DEF_" + udfIdx + " <= '" + userDefTo + "' ) ");
              }else{              
                sqlStat.append("(");
                if ( !Utility.isEmpty(userDefFrom) ) { //only first value entered               
                  sqlStat.append(" D.USER_DEF_" + udfIdx + " >= '" + userDefFrom + "' ");               
                }else{ //only 2nd value entered
                  sqlStat.append(" D.USER_DEF_" + udfIdx + "  <= '" + userDefTo + "' ");
                }
                if (DataSourceFactory.getDatabaseType() == DataSourceFactory.DB_ORACLE) {              
                  sqlStat.append(" AND LENGTH(D.USER_DEF_" + udfIdx + ") > 0 ");              
                }else{
                  sqlStat.append(" AND D.USER_DEF_" + udfIdx + " <> '' ");
                }
                sqlStat.append(")");
              }
            } else {
              String sUserDef=userDefFrom;
              String getUserDef=TextUtility.convert(sUserDef);//convert big5 to gb or gb to big5
              String sGetUserDef=sUserDef;
              if(!TextUtility.checkContainsOperandChar(userDefFrom)){
                sGetUserDef = sUserDef + " OR " + getUserDef;
                if(isRelationWord){  //relatioanal word
                  List relationalUserDefList = dmsRelationalWordDaobject.getRelationalWordListByKeyWord(userDefFrom);
                  for(int i=0;i<relationalUserDefList.size();i++){
                    dmsRelationalWord = (DmsRelationalWord)relationalUserDefList.get(i);
                    String relationUserDef = dmsRelationalWord.getWord();
                    sGetUserDef += " OR " + TextUtility.convert(relationUserDef) + " OR " +relationUserDef ;
                  }
                }
              }
              
              HashMap mResult = getCriteriaCombination("D.USER_DEF_" + udfIdx, sGetUserDef, userDefExactMatch);
              sqlStat.append(mResult.get("SQL"));
              repe += TextUtility.parseInteger( (String) mResult.get("?"));
              mFieldMap.put("USER_DEF_" + udfIdx, mResult.get("fieldResult"));
            }
          }
        }
        
        
        if (!Utility.isEmpty(docSearchForm.getUserDefinedFieldID())) {
//        int tempCounter = 0;
          tmpCounter++;
          if (tmpCounter > 1) {
            sqlStat.append(" " + docSearchForm.getUserDefinedFieldOption() + " ");
          }
          
//        DmsDocumentDetail docDetail = (DmsDocumentDetail) docDetailList.get(0);
          
          log.debug("the user defined field option:" + docSearchForm.getUserDefinedFieldOption());
          //sqlStat.append(" ( DD.USER_DEFINED_FIELD_ID =" + docSearchForm.getUserDefinedFieldID());
          sqlStat.append(" ( DI.USER_DEFINED_FIELD_ID =" + docSearchForm.getUserDefinedFieldID());
          
          int fieldTmpCount = 0;
          int a = 0;
          DmsDocumentDetail docDetail = new DmsDocumentDetail();
          
          docDetailList = docRetrievalManager.sortDocDetailList(docDetailList);
          
          for (int i = 0; i < docDetailList.size(); i++) {
            docDetail = (DmsDocumentDetail) docDetailList.get(i);
            int pos = 0;
            //pos=docRetrievalManager.getUDFDetailPos(TextUtility.parseIntegerObj(docSearchForm.getUserDefinedFieldID()),docDetail.getUserDefinedFieldDetailID());
            pos = i + 1;
            
            log.debug("the field type is:"+docDetail.getFieldType().toString());
            if (pos > 0) {
              if (!Utility.isEmpty(docDetail.getFieldValue()) || docDetail.getDateValue() != null ||
                  docDetail.getToDateValue() != null || docDetail.getNumericValue() != null ||
                  docDetail.getToNumericValue() != null) {
                fieldTmpCount++;
                a++;
                //if (a == 1)  sqlStat.append(" AND ");
                //if (fieldTmpCount > 1) {
                sqlStat.append(" " + docDetail.getSearchOption() + " ");
                //}
                sqlStat.append(" ( ");
                // sqlStat.append(" ( DI.USER_DEFINED_FIELD_DETAIL_ID = " + docDetail.getUserDefinedFieldDetailID().toString());
                // sqlStat.append(" AND ");
                
                if ( (SysUserDefinedIndexDetail.STRING_FIELD.equals(docDetail.getFieldType()) ||
                    docDetail.getFieldType().startsWith("CUST")) && !Utility.isEmpty(docDetail.getFieldValue())) {
                  
                  String sFieldValue=docDetail.getFieldValue();
                  String sValue=TextUtility.convert(sFieldValue);//convert big5 to gb or gb to big5
                  String sGetFieldValue=sFieldValue;
                  if(!TextUtility.checkContainsOperandChar(docDetail.getFieldValue())){
                    sGetFieldValue=sFieldValue+" OR "+sValue;
                    if(isRelationWord){//relatioanal word
                      List relationalFieldValueList = dmsRelationalWordDaobject.getRelationalWordListByKeyWord(docDetail.getFieldValue());
                      for( int n=0;n<relationalFieldValueList.size();n++){
                        dmsRelationalWord = (DmsRelationalWord)relationalFieldValueList.get(n);
                        String relationFieldValue = dmsRelationalWord.getWord();
                        sGetFieldValue += " OR " + TextUtility.convert(relationFieldValue) + " OR " +relationFieldValue ;
                      }
                    }
                  }
                  
                  HashMap mResult = getCriteriaCombination("DI.INDEX_" + pos, sGetFieldValue, docDetail.getExactMatch());
                  sqlStat.append(mResult.get("SQL"));
                  repe += TextUtility.parseInteger( (String) mResult.get("?"));
                  
                  List tmpList = (List) mResult.get("fieldResult");
                  mFieldMap.put("UDF_DETAIL_" + docDetail.getUserDefinedFieldDetailID() + "_FIELDVALUE", mResult.get("fieldResult"));
                } else if ( SysUserDefinedIndexDetail.FIELD_TYPE_SELECT_DATABASE.equals(docDetail.getFieldType())) { //select value
                  String sFieldValue=docDetail.getFieldValue();
                  String sValue=TextUtility.convert(sFieldValue);//convert big5 to gb or gb to big5
                  String sGetFieldValue=sFieldValue;
                  if(!TextUtility.checkContainsOperandChar(docDetail.getFieldValue())){
                    sGetFieldValue=sFieldValue+" OR "+sValue;
                    if(isRelationWord){//relatioanal word
                      List relationalFieldValueList = dmsRelationalWordDaobject.getRelationalWordListByKeyWord(docDetail.getFieldValue());
                      for( int n=0;n<relationalFieldValueList.size();n++){
                        dmsRelationalWord = (DmsRelationalWord)relationalFieldValueList.get(n);
                        String relationFieldValue = dmsRelationalWord.getWord();
                        sGetFieldValue += " OR " + TextUtility.convert(relationFieldValue) + " OR " +relationFieldValue ;
                      }
                    }
                  }
                  
                  HashMap mResult = getCriteriaCombination("DI.INDEX_" + pos, sGetFieldValue, true);
                  sqlStat.append(mResult.get("SQL"));
                  repe += TextUtility.parseInteger( (String) mResult.get("?"));
                  
                  List tmpList = (List) mResult.get("fieldResult");
                  mFieldMap.put("UDF_DETAIL_" + docDetail.getUserDefinedFieldDetailID() + "_FIELDVALUE", mResult.get("fieldResult"));                  
                  
                } else if (SysUserDefinedIndexDetail.NUMBER_FIELD.equals(docDetail.getFieldType())) { //number value
                  
                  log.debug("the numberic value:"+docDetail.getNumericValue());
                  if (docDetail.getNumericValue() != null && docDetail.getToNumericValue() != null) {
                    sqlStat.append(" (DI.INDEX_" + pos + ">= '" + IndexManager.numberPad(docDetail.getNumericValue()) + "' AND DI.INDEX_" + pos + " <= '" +
                        IndexManager.numberPad(docDetail.getToNumericValue()) + "' ) ");
                  } else if (docDetail.getNumericValue() != null && docDetail.getToNumericValue() == null) { //only first value entered
                    sqlStat.append(" (DI.INDEX_" + pos + " >= '" + IndexManager.numberPad(docDetail.getNumericValue()) + "' ) ");
                  } else if (docDetail.getNumericValue() == null && docDetail.getToNumericValue() != null) { //only 2nd value entered
                    sqlStat.append(" (DI.INDEX_" + pos + " <= '" + IndexManager.numberPad(docDetail.getToNumericValue()) + "' ) ");
                  }
                  
                } else if (SysUserDefinedIndexDetail.DATE_FIELD.equals(docDetail. //Date range
                    getFieldType())) {
                  
                  if (docDetail.getDateValue() != null && docDetail.getToDateValue() != null) {
                    //sqlStat.append(" (DI.INDEX_" + pos + " >= '" + DateField.dateToString(docDetail.getDateValue()) + "' AND DI.INDEX_" + pos + " <= '" +
                    //               DateField.dateToString(docDetail.getToDateValue()) + "' ) ");
                    sqlStat.append(" (DI.INDEX_" + pos + " >= '" + TextUtility.formatTimestampToIndex(docDetail.getDateValue()) + "' AND DI.INDEX_" + pos + " <= '" +
                        TextUtility.formatTimestampToIndex(docDetail.getToDateValue()) + "' ) ");
                  } else if (docDetail.getDateValue() != null && docDetail.getToDateValue() == null) { //only first value entered
                    //sqlStat.append(" (DI.INDEX_" + pos + " >= '" + DateField.dateToString(docDetail.getDateValue()) + "' ) ");
                    sqlStat.append(" (DI.INDEX_" + pos + " >= '" + TextUtility.formatTimestampToIndex(docDetail.getDateValue()) + "' ) ");
                  } else if (docDetail.getDateValue() == null && docDetail.getToDateValue() != null) { //only 2nd value entered
                    //sqlStat.append(" (DI.INDEX_" + pos + " <= '" + DateField.dateToString(docDetail.getToDateValue()) + "' ) ");
                    sqlStat.append(" (DI.INDEX_" + pos + " <= '" + TextUtility.formatTimestampToIndex(docDetail.getToDateValue()) + "' ) ");
                  }
                }
                //sqlStat.append(" ) )  ");
                sqlStat.append(" ) ");
              } //end if
            } //end if after for
          } //end for
          sqlStat.append(" )  ");
          repe++;
        }
        
        //if (DmsOperationConstant.ATTR_NEST_FILTER_OPERATION.equals(docSearchForm.getOpMode()) ){
        if (!Utility.isEmpty(outerCriteria)) {
          outerCriteria = outerCriteria + " AND " + sqlStat.substring(startPos, sqlStat.length());
        } else {
          outerCriteria = sqlStat.substring(startPos, sqlStat.length());
        }
        //}
        sqlStat.append(" ) ");
        
        if (rootIDs.size() > 0) {
          sqlStat.append(" AND ( ");
          for (int i = 0; i < rootIDs.size(); i++) {
            sqlStat.append(" D.ROOT_ID = ? ");
            if (i + 1 < rootIDs.size()) {
              sqlStat.append(" OR ");
            }
          }
          sqlStat.append(" )  ");
        } else {
          sqlStat.append(" AND D.ROOT_ID = ?   ");
        }
        
        //Apend the prv outer search criteria
        if (DmsOperationConstant.ATTR_NEST_FILTER_OPERATION.equals(docSearchForm.getOpMode()) &&
            !Utility.isEmpty(docSearchForm.getOuterCriteria())) {
          sqlStat.append(" AND (  " + docSearchForm.getOuterCriteria() + " ) ");
        } else if (DmsOperationConstant.ATTR_EXPORT_OPERATION.equals(docSearchForm.getOpMode()) ||
            DmsOperationConstant.ATTR_COMBINE_TIFF_OPERATION.equals(docSearchForm.getOpMode())) {
          if (DmsOperationConstant.ATTR_NEST_FILTER_OPERATION.equals(docSearchForm.getPrvOpMode()) &&
              !Utility.isEmpty(docSearchForm.getOuterCriteria())) {
            sqlStat.append(" AND (  " + docSearchForm.getOuterCriteria() + " ) ");
          }
        }
        
        
        sqlStat.append("AND ((D.EFFECTIVE_START_DATE IS NULL OR D.EFFECTIVE_START_DATE <= ?) OR D.OWNER_ID=?) ");
        if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
          sqlStat.append("       AND ((D.EFFECTIVE_END_DATE IS NULL OR D.EFFECTIVE_END_DATE > ?) ");
          sqlStat.append("       OR D.OWNER_ID = ?) ");
        }
//      sqlStat.append("  D.DOCUMENT_TYPE = 'D' AND D.RECORD_STATUS = ? ORDER BY D.ROOT_ID,D.ID");
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        
        
        if(runSeq == 1){
          sqlStat.append("ORDER BY  D.DOCUMENT_TYPE ASC ");
        }else{
          sqlStat.append("ORDER BY D.DOCUMENT_TYPE DESC  ");
          
          if (docSearchForm.isSortable()) {
            
            String sortAttribute = docSearchForm.getSortAttribute();
            if (sortAttribute.indexOf(".") < 0) {
              sortAttribute = "D." + sortAttribute;
            }
            
            sqlStat.append(", " + sortAttribute + " " + searchForm.getSortOrder() + " ");
          }
        }
        int i = 0;
        
        // Get total number of record return.
        StringBuffer sbResult = new StringBuffer("SELECT COUNT(DISTINCT(D.ID)) FROM ");
        int idx = sqlStat.indexOf("FROM ");
        sbResult.append(sqlStat.substring(idx + 5));
        if (sbResult.indexOf("ORDER BY") >= 0) {
          sbResult = new StringBuffer(sbResult.substring(0, sbResult.indexOf("ORDER BY") - 1));
        }
        log.info("COUNT SQL: " + sbResult);
        sqlStatCnt = sbResult;
        
        //Used for nest filtering
        String[] oldCriteriaValue = docSearchForm.getOuterCriteriaValue();
        // runSeq == 1 not need split the page size
        if(runSeq != 1){
          preStatCnt = dbConn.prepareStatement(sqlStatCnt.toString());
          
          String tmp1Cnt[] = null;
          
          this.setPrepareStatement(preStatCnt, ++i, GlobalConstant.RECORD_STATUS_ACTIVE);
          
          if (!Utility.isEmpty(docSearchForm.getDocumentName())) {
            
            List fieldList = (List) mFieldMap.get("DOCUMENT_NAME");
            for (int j = 0; j < fieldList.size(); j++) {
              log.debug("(String) fieldList.get(j) = " + fieldList);
              setPrepareStatement(preStatCnt, ++i, (String) fieldList.get(j));
            }
          }
          
          if (!Utility.isEmpty(docSearchForm.getDocumentType())) {
            List fieldList = (List) mFieldMap.get("DOCUMENT_TYPE");
            for (int j = 0; j < fieldList.size(); j++) {
              setPrepareStatement(preStatCnt, ++i, (String) fieldList.get(j));
            }
          }
          
          if (!Utility.isEmpty(docSearchForm.getSearchPriority())) {
            List fieldList = (List) mFieldMap.get("PRIORITY");
            for (int j = 0; j < fieldList.size(); j++) {
              setPrepareStatement(preStatCnt, ++i, (String) fieldList.get(j));
            }
          }        
          
          if (!Utility.isEmpty(docSearchForm.getReferenceNo())) {
            List fieldList = (List) mFieldMap.get("REFERENCE_NO");
            for (int j = 0; j < fieldList.size(); j++) {
              setPrepareStatement(preStatCnt, ++i, (String) fieldList.get(j));
            }
          }
          
          if (!Utility.isEmpty(docSearchForm.getDescription())) {
            List fieldList = (List) mFieldMap.get("DESCRIPTION");
            for (int j = 0; j < fieldList.size(); j++) {
              setPrepareStatement(preStatCnt, ++i, (String) fieldList.get(j));
            }
          }
          
          if (!Utility.isEmpty(docSearchForm.getCreatorID())) {
            List fieldList = (List) mFieldMap.get("CREATOR_ID");
            for (int j = 0; j < fieldList.size(); j++) {
              setPrepareStatement(preStatCnt, ++i, (String) fieldList.get(j));
            }
          }
          
          //iterate userDef1 to userDef10 using reflection
          for(int udfIdx = 1 ; udfIdx<=totalFieldCount ; udfIdx++){
            Class cls = Class.forName(ListDmsDocumentForm.class.getName());
            Method userDefMethod = cls.getMethod("getUserDef"+udfIdx,null);
            String userDefFrom = (String)userDefMethod.invoke(docSearchForm, null);
            Method userDefToMethod = cls.getMethod("getUserDef"+udfIdx+"To",null);
            String userDefTo = (String)userDefToMethod.invoke(docSearchForm, null);
            Method userDefDataTypeMethod = cls.getMethod("getUserDef"+udfIdx+"DataType",null);
            String userDefDataType = (String)userDefDataTypeMethod.invoke(docSearchForm, null);
            
            
            if ( (!Utility.isEmpty(userDefFrom)) || (!Utility.isEmpty(userDefTo))) {
              if (!DmsDefaultProfileSetting.FIELD_TYPE_DATE.equals(userDefDataType)) {
                List fieldList = (List) mFieldMap.get("USER_DEF_"+udfIdx);
                for (int j = 0; j < fieldList.size(); j++) {
                  setPrepareStatement(preStatCnt, ++i, (String) fieldList.get(j));
                }              
              }
            }
          }         
          
          if (!Utility.isEmpty(docSearchForm.getUserDefinedFieldID())) {
            for (int j = 0; j < docDetailList.size(); j++) {
              DmsDocumentDetail docDetail = (DmsDocumentDetail) docDetailList.get(j);
              
              List fieldList = (List) mFieldMap.get("UDF_DETAIL_" + docDetail.getUserDefinedFieldDetailID() + "_FIELDVALUE");
              if (!Utility.isEmpty(fieldList)) {
                for (int k = 0; k < fieldList.size(); k++) {
                  setPrepareStatement(preStatCnt, ++i, (String) fieldList.get(k));
                }
              }
            }
          }
          
          if (rootIDs.size() > 0) {
            for (int j = 0; j < rootIDs.size(); j++) {
              Integer rootID = TextUtility.parseIntegerObj( (String) rootIDs.get(j));
              log.debug("rooid = " + rootID);
              setPrepareStatement(preStatCnt, ++i, rootID);
            }
          } else {
            setPrepareStatement(preStatCnt, ++i, docSearchForm.getRootID());
            log.debug("rooid = " + docSearchForm.getRootID());
          }
          
          
          if (DmsOperationConstant.ATTR_NEST_FILTER_OPERATION.equals(
              docSearchForm.getOpMode()) && oldCriteriaValue != null) {
            log.debug("        ....oldCriteriaValue = " + oldCriteriaValue.length);
            for (int o = 0; o < oldCriteriaValue.length; o++) {
              String tmpValue = oldCriteriaValue[o];
              if (!Utility.isEmpty(tmpValue) && !"null".equals(tmpValue)) {
                setPrepareStatement(preStatCnt, ++i, tmpValue);
              }
            }
            
          } else if (DmsOperationConstant.ATTR_EXPORT_OPERATION.equals(docSearchForm.getOpMode()) ||
              DmsOperationConstant.ATTR_COMBINE_TIFF_OPERATION.equals(docSearchForm.getOpMode())) {
            if (DmsOperationConstant.ATTR_NEST_FILTER_OPERATION.equals(docSearchForm.getPrvOpMode()) &&
                oldCriteriaValue != null) {
              log.debug("        ....oldCriteriaValue = " + oldCriteriaValue.length);
              for (int o = 0; o < oldCriteriaValue.length; o++) {
                String tmpValue = oldCriteriaValue[o];
                if (!Utility.isEmpty(tmpValue) && !"null".equals(tmpValue)) {
                  setPrepareStatement(preStatCnt, ++i, tmpValue);
                }
              }
            }
          }
          
          this.setPrepareStatement(preStatCnt, ++i, currTime);
          this.setPrepareStatement(preStatCnt, ++i, this.sessionContainer.getUserRecordID());
          if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
            this.setPrepareStatement(preStatCnt, ++i, oneDayBeforeCurrTime);
            this.setPrepareStatement(preStatCnt, ++i, this.sessionContainer.getUserRecordID());
          }
          
          rsCnt = preStatCnt.executeQuery();
          if (rsCnt.next()) {
            totalNumOfRecord = rsCnt.getInt(1);
          }
          log.debug("totalNumOfRecord =  " + totalNumOfRecord);
          try {
            rsCnt.close();
          } catch (Exception ignore) {} finally {
            rsCnt = null;
          }
          try {
            preStatCnt.close();
          } catch (Exception ignore) {} finally {
            preStatCnt = null;
          }
          log.debug("search result option = " + docSearchForm.getSearchResultOpt() + " = " + DmsOperationConstant.SEARCH_RESULT_ALL);
          
          // if runSeq ==1 ,get the all search reasults 
          if (!DmsOperationConstant.SEARCH_RESULT_ALL.equals(docSearchForm.getSearchResultOpt())) {
            // Retrieve the result in row basis.
            sqlStat = this.getSelectListSQL(sqlStat, startOffset, pageSize);
          } else {
            log.info("SELECT SQL: " + sqlStat);
          }
          
        }
        
        
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        
        String tmp1[] = null;
        i = 0;
        List outerCriteriaValue = new ArrayList();
        
        setPrepareStatement(preStat, ++i, GlobalConstant.RECORD_STATUS_ACTIVE);
        
        if (!Utility.isEmpty(docSearchForm.getDocumentName())) {
          List fieldList = (List) mFieldMap.get("DOCUMENT_NAME");
          for (int j = 0; j < fieldList.size(); j++) {
            setPrepareStatement(preStat, ++i, (String) fieldList.get(j));
            outerCriteriaValue.add( fieldList.get(j));
          }
        } else {
          outerCriteriaValue.add("null");
        }
        
        if (!Utility.isEmpty(docSearchForm.getDocumentType())) {
          List fieldList = (List) mFieldMap.get("DOCUMENT_TYPE");
          for (int j = 0; j < fieldList.size(); j++) {
            setPrepareStatement(preStat, ++i, (String) fieldList.get(j));
            outerCriteriaValue.add( fieldList.get(j));
          }
        } else {
          outerCriteriaValue.add("null");
        }
        
        if (!Utility.isEmpty(docSearchForm.getSearchPriority())) {
          List fieldList = (List) mFieldMap.get("PRIORITY");
          for (int j = 0; j < fieldList.size(); j++) {
            setPrepareStatement(preStat, ++i, (String) fieldList.get(j));
            outerCriteriaValue.add( fieldList.get(j));
          }
        } else {
          outerCriteriaValue.add("null");
        }
        
        if (!Utility.isEmpty(docSearchForm.getReferenceNo())) {
          List fieldList = (List) mFieldMap.get("REFERENCE_NO");
          for (int j = 0; j < fieldList.size(); j++) {
            setPrepareStatement(preStat, ++i, (String) fieldList.get(j));
            outerCriteriaValue.add( fieldList.get(j));
          }
        } else {
          outerCriteriaValue.add("null");
        }
        
        if (!Utility.isEmpty(docSearchForm.getDescription())) {
          List fieldList = (List) mFieldMap.get("DESCRIPTION");
          for (int j = 0; j < fieldList.size(); j++) {
            setPrepareStatement(preStat, ++i, (String) fieldList.get(j));
            outerCriteriaValue.add( fieldList.get(j));
          }
        } else {
          outerCriteriaValue.add("null");
        }
        
        if (!Utility.isEmpty(docSearchForm.getCreatorID())) {
          List fieldList = (List) mFieldMap.get("CREATOR_ID");
          for (int j = 0; j < fieldList.size(); j++) {
            setPrepareStatement(preStat, ++i, (String) fieldList.get(j));
            outerCriteriaValue.add( fieldList.get(j));
          }
        } else {
          outerCriteriaValue.add("null");
        }
        
        //iterate userDef1 to userDef10 using reflection
        for(int udfIdx = 1 ; udfIdx<=totalFieldCount ; udfIdx++){
          Class cls = Class.forName(ListDmsDocumentForm.class.getName());
          Method userDefMethod = cls.getMethod("getUserDef"+udfIdx,null);
          String userDefFrom = (String)userDefMethod.invoke(docSearchForm, null);
          Method userDefToMethod = cls.getMethod("getUserDef"+udfIdx+"To",null);
          String userDefTo = (String)userDefToMethod.invoke(docSearchForm, null);
          Method userDefDataTypeMethod = cls.getMethod("getUserDef"+udfIdx+"DataType",null);
          String userDefDataType = (String)userDefDataTypeMethod.invoke(docSearchForm, null);
          
          
          if ( (!Utility.isEmpty(userDefFrom)) || (!Utility.isEmpty(userDefTo))) {
            if (!DmsDefaultProfileSetting.FIELD_TYPE_DATE.equals(userDefDataType)) {
              List fieldList = (List) mFieldMap.get("USER_DEF_"+udfIdx);
              for (int j = 0; j < fieldList.size(); j++) {
                setPrepareStatement(preStat, ++i, (String) fieldList.get(j));
                outerCriteriaValue.add( fieldList.get(j));
              }           
            } else {
              outerCriteriaValue.add("null");
            }
          } else {
            outerCriteriaValue.add("null");
          }
        }
        
        if (!Utility.isEmpty(docSearchForm.getUserDefinedFieldID())) {
          for (int j = 0; j < docDetailList.size(); j++) {
            DmsDocumentDetail docDetail = (DmsDocumentDetail) docDetailList.get(j);
            List fieldList = (List) mFieldMap.get("UDF_DETAIL_" + docDetail.getUserDefinedFieldDetailID() + "_FIELDVALUE");
            if (!Utility.isEmpty(fieldList)) {
              for (int k = 0; k < fieldList.size(); k++) {
                
                setPrepareStatement(preStat, ++i, (String) fieldList.get(k));
                outerCriteriaValue.add( fieldList.get(k));
                log.debug("the field is:" + (String) fieldList.get(k));
              }
            } else {
              outerCriteriaValue.add("null");
            }
            
          }
        }
        
        if (rootIDs.size() > 0) {
          for (int j = 0; j < rootIDs.size(); j++) {
            Integer rootID = TextUtility.parseIntegerObj( (String) rootIDs.get(
                j));
            setPrepareStatement(preStat, ++i, rootID);
          }
        } else {
          setPrepareStatement(preStat, ++i, docSearchForm.getRootID());
        }
        
        //Used for nest filtering
        //String[] oldCriteriaValue = docSearchForm.getOuterCriteriaValue();
        if (DmsOperationConstant.ATTR_NEST_FILTER_OPERATION.equals(
            docSearchForm.getOpMode()) && oldCriteriaValue != null) {
          for (int o = 0; o < oldCriteriaValue.length; o++) {
            String tmpValue = oldCriteriaValue[o];
            if (!Utility.isEmpty(tmpValue) && !"null".equals(tmpValue)) {
              setPrepareStatement(preStat, ++i, oldCriteriaValue[o]);
            }
          }
        } else if (DmsOperationConstant.ATTR_EXPORT_OPERATION.equals(
            docSearchForm.getOpMode()) ||
            DmsOperationConstant.
            ATTR_COMBINE_TIFF_OPERATION.equals(docSearchForm.getOpMode())) {
          if (DmsOperationConstant.ATTR_NEST_FILTER_OPERATION.equals(
              docSearchForm.getPrvOpMode()) &&
              oldCriteriaValue != null) {
            for (int o = 0; o < oldCriteriaValue.length; o++) {
              String tmpValue = oldCriteriaValue[o];
              if (!Utility.isEmpty(tmpValue) && !"null".equals(tmpValue)) {
                setPrepareStatement(preStat, ++i, oldCriteriaValue[o]);
              }
            }
            
          }
        }
        
        setPrepareStatement(preStat, ++i, currTime);
        setPrepareStatement(preStat, ++i, this.sessionContainer.getUserRecordID());
        if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
          setPrepareStatement(preStat, ++i, oneDayBeforeCurrTime);
          setPrepareStatement(preStat, ++i, this.sessionContainer.getUserRecordID());
        }
        
        rs = preStat.executeQuery();
        if (!DmsOperationConstant.SEARCH_RESULT_ALL.equals(docSearchForm.getSearchResultOpt())) {        
          if(runSeq != 1){
            this.positionCursor(rs, startOffset, pageSize);
          }
        }       
        int j = 0;
        //  return the not duplic document id
        if(runSeq == 1){
          while (rs.next()) {
            if("L".equals(getResultSetString(rs, "DOCUMENT_TYPE"))){
              if(!tempResult.contains(getResultSetInteger(rs, "SOURCE_DOC_ID"))){
                tempResult.add(getResultSetInteger(rs, "SOURCE_DOC_ID"));  
                result.add(getResultSetInteger(rs, "ID"));
              }
            }//if the SOURCE_DOC_ID == null then the record is not a shot cut type
            else{
              tempResult.add(getResultSetInteger(rs, "ID"));  
              result.add(getResultSetInteger(rs, "ID"));
            }
          }        
        }else{
          while (rs.next() && rowLoopCnt < pageSize) {
            DmsDocument tmpDmsDocument = new DmsDocument();
            tmpDmsDocument.setID(getResultSetInteger(rs, "ID"));
            tmpDmsDocument.setDocumentName(getResultSetString(rs, "DOCUMENT_NAME"));
            tmpDmsDocument.setDocumentType(getResultSetString(rs, "DOCUMENT_TYPE"));
            tmpDmsDocument.setParentID(getResultSetInteger(rs, "PARENT_ID"));
            tmpDmsDocument.setRootID(getResultSetInteger(rs, "ROOT_ID"));
            tmpDmsDocument.setPriority(getResultSetString(rs, "PRIORITY"));
            tmpDmsDocument.setCreateType(getResultSetString(rs, "CREATE_TYPE"));
            tmpDmsDocument.setEffectiveStartDate(getResultSetTimestamp(rs, "EFFECTIVE_START_DATE"));
            tmpDmsDocument.setEffectiveEndDate(getResultSetTimestamp(rs, "EFFECTIVE_END_DATE"));
            tmpDmsDocument.setReminderAmount(getResultSetInteger(rs, "REMINDER_AMOUNT"));
            tmpDmsDocument.setReminderType(getResultSetString(rs, "REMINDER_TYPE"));
            tmpDmsDocument.setNotificationWay(getResultSetStringAry(rs, "NOTIFICATION_WAY", ";"));
            tmpDmsDocument.setOwnerID(getResultSetInteger(rs, "OWNER_ID"));
            tmpDmsDocument.setReferenceNo(getResultSetString(rs, "REFERENCE_NO"));
            tmpDmsDocument.setDescription(getResultSetString(rs, "DESCRIPTION"));
            tmpDmsDocument.setItemSize(getResultSetInteger(rs, "ITEM_SIZE"));
            tmpDmsDocument.setItemStatus(getResultSetString(rs, "ITEM_STATUS"));
            tmpDmsDocument.setCheckoutID(getResultSetInteger(rs, "CHECKOUT_ID"));
            tmpDmsDocument.setAlertEditID(getResultSetInteger(rs, "ALERT_EDIT_ID"));
            tmpDmsDocument.setAlertInviteID(getResultSetInteger(rs, "ALERT_INVITE_ID"));
            tmpDmsDocument.setExtRef(getResultSetString(rs, "EXT_REF"));            
            tmpDmsDocument.setUserDef1(getResultSetString(rs, "USER_DEF_1"));
            tmpDmsDocument.setUserDef2(getResultSetString(rs, "USER_DEF_2"));
            tmpDmsDocument.setUserDef3(getResultSetString(rs, "USER_DEF_3"));
            tmpDmsDocument.setUserDef4(getResultSetString(rs, "USER_DEF_4"));
            tmpDmsDocument.setUserDef5(getResultSetString(rs, "USER_DEF_5"));
            tmpDmsDocument.setUserDef6(getResultSetString(rs, "USER_DEF_6"));
            tmpDmsDocument.setUserDef7(getResultSetString(rs, "USER_DEF_7"));
            tmpDmsDocument.setUserDef8(getResultSetString(rs, "USER_DEF_8"));
            tmpDmsDocument.setUserDef9(getResultSetString(rs, "USER_DEF_9"));
            tmpDmsDocument.setUserDef10(getResultSetString(rs, "USER_DEF_10"));
            tmpDmsDocument.setRecordStatus(getResultSetString(rs, "RECORD_STATUS"));
            tmpDmsDocument.setUpdateCount(getResultSetInteger(rs, "UPDATE_COUNT"));
            tmpDmsDocument.setCreatorID(getResultSetInteger(rs, "CREATOR_ID"));
            tmpDmsDocument.setCreateDate(getResultSetTimestamp(rs, "CREATE_DATE"));
            tmpDmsDocument.setUpdaterID(getResultSetInteger(rs, "UPDATER_ID"));
            tmpDmsDocument.setUpdateDate(getResultSetTimestamp(rs, "UPDATE_DATE"));
            if (!Utility.isEmpty(docSearchForm.getUserDefinedFieldID())) {
              tmpDmsDocument.setUserDefinedFieldID(getResultSetInteger(rs, "USER_DEFINED_FIELD_ID"));
            }
            
            tmpDmsDocument.setCreatorName(UserInfoFactory.getUserFullName(tmpDmsDocument.getCreatorID()));
            tmpDmsDocument.setUpdaterName(UserInfoFactory.getUserFullName(tmpDmsDocument.getUpdaterID()));
            tmpDmsDocument.setRecordCount(totalNumOfRecord);
            tmpDmsDocument.setRowNum(startOffset++);
            
            if (j == 0) { //set the value temp for later retrieval
              tmpDmsDocument.setOuterCriteria(outerCriteria);
              int oldSize = 0;
              if (DmsOperationConstant.ATTR_NEST_FILTER_OPERATION.equals(
                  docSearchForm.getOpMode()) && oldCriteriaValue != null) {
                oldSize = oldCriteriaValue.length;
              } else if (DmsOperationConstant.ATTR_EXPORT_OPERATION.equals(
                  docSearchForm.getOpMode()) || DmsOperationConstant.ATTR_COMBINE_TIFF_OPERATION.equals(docSearchForm.getOpMode())) {
                if (DmsOperationConstant.ATTR_NEST_FILTER_OPERATION.equals(
                    docSearchForm.getOpMode()) && oldCriteriaValue != null) {
                  oldSize = oldCriteriaValue.length;
                }
              }
              
              int outerSize = outerCriteriaValue == null ? 0 :
                outerCriteriaValue.size();
              String[] newCriteriaValue = new String[oldSize + outerSize];
              int newCriteriaNum = 0;
              if (DmsOperationConstant.ATTR_NEST_FILTER_OPERATION.equals(
                  docSearchForm.getOpMode()) && oldCriteriaValue != null) {
                for (int k = 0; k < oldCriteriaValue.length; k++) {
                  newCriteriaValue[newCriteriaNum] = oldCriteriaValue[k];
                  newCriteriaNum++;
                }
              } else if (DmsOperationConstant.ATTR_EXPORT_OPERATION.equals(
                  docSearchForm.getOpMode()) || DmsOperationConstant.ATTR_COMBINE_TIFF_OPERATION.equals(docSearchForm.getOpMode())) {
                if (DmsOperationConstant.ATTR_NEST_FILTER_OPERATION.equals(
                    docSearchForm.getOpMode()) && oldCriteriaValue != null) {
                  for (int k = 0; k < oldCriteriaValue.length; k++) {
                    newCriteriaValue[newCriteriaNum] = oldCriteriaValue[k];
                    newCriteriaNum++;
                  }
                }
              }
              
              for (int k = 0; k < outerCriteriaValue.size(); k++) {
                newCriteriaValue[newCriteriaNum] = (String) outerCriteriaValue.get(k);
                newCriteriaNum++;
              }
              tmpDmsDocument.setOuterCriteriaValue(newCriteriaValue);
              j++;
            }
            
            if (!DmsOperationConstant.SEARCH_RESULT_ALL.equals(docSearchForm.getSearchResultOpt())) {
              ++rowLoopCnt;
            }
            
            result.add(tmpDmsDocument);
          }
        }
        
        
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
        try {
          rsCnt.close();
        } catch (Exception ignore) {} finally {
          rsCnt = null;
        }
        try {
          preStatCnt.close();
        } catch (Exception ignore) {} finally {
          preStatCnt = null;
        }
      }
    }
  }
  
  /**
   * Gets the document information from rs set to new DmsDocument Object
   *
   * @param rs 
   * @return the geted value's DmsDocument Object
   
   * @throws ApplicationException
   * 
   */
  private DmsDocument  parseObjectFromResultSet(ResultSet rs) throws ApplicationException{    
    DmsDocument tmpDmsDocument = new DmsDocument();
    try{
      tmpDmsDocument.setID(getResultSetInteger(rs, "ID"));
      tmpDmsDocument.setDocumentName(getResultSetString(rs, "DOCUMENT_NAME"));
      tmpDmsDocument.setDocumentType(getResultSetString(rs, "DOCUMENT_TYPE"));
      tmpDmsDocument.setParentID(getResultSetInteger(rs, "PARENT_ID"));
      tmpDmsDocument.setRootID(getResultSetInteger(rs, "ROOT_ID"));
      tmpDmsDocument.setPriority(getResultSetString(rs, "PRIORITY"));
      tmpDmsDocument.setCreateType(getResultSetString(rs, "CREATE_TYPE"));
      tmpDmsDocument.setEffectiveStartDate(getResultSetTimestamp(rs, "EFFECTIVE_START_DATE"));
      tmpDmsDocument.setEffectiveEndDate(getResultSetTimestamp(rs, "EFFECTIVE_END_DATE"));
      tmpDmsDocument.setReminderAmount(getResultSetInteger(rs, "REMINDER_AMOUNT"));
      tmpDmsDocument.setReminderType(getResultSetString(rs, "REMINDER_TYPE"));
      tmpDmsDocument.setNotificationWay(getResultSetStringAry(rs, "NOTIFICATION_WAY", ";"));
      tmpDmsDocument.setOwnerID(getResultSetInteger(rs, "OWNER_ID"));
      tmpDmsDocument.setReferenceNo(getResultSetString(rs, "REFERENCE_NO"));
      tmpDmsDocument.setDescription(getResultSetString(rs, "DESCRIPTION"));
      tmpDmsDocument.setItemSize(getResultSetInteger(rs, "ITEM_SIZE"));
      tmpDmsDocument.setItemStatus(getResultSetString(rs, "ITEM_STATUS"));
      tmpDmsDocument.setCheckoutID(getResultSetInteger(rs, "CHECKOUT_ID"));
      tmpDmsDocument.setAlertEditID(getResultSetInteger(rs, "ALERT_EDIT_ID"));
      tmpDmsDocument.setAlertInviteID(getResultSetInteger(rs, "ALERT_INVITE_ID"));
      tmpDmsDocument.setExtRef(getResultSetString(rs, "EXT_REF"));   
      
      tmpDmsDocument.setUserDef1(getResultSetString(rs, "USER_DEF_1"));
      tmpDmsDocument.setUserDef2(getResultSetString(rs, "USER_DEF_2"));
      tmpDmsDocument.setUserDef3(getResultSetString(rs, "USER_DEF_3"));
      tmpDmsDocument.setUserDef4(getResultSetString(rs, "USER_DEF_4"));
      tmpDmsDocument.setUserDef5(getResultSetString(rs, "USER_DEF_5"));
      tmpDmsDocument.setUserDef6(getResultSetString(rs, "USER_DEF_6"));
      tmpDmsDocument.setUserDef7(getResultSetString(rs, "USER_DEF_7"));
      tmpDmsDocument.setUserDef8(getResultSetString(rs, "USER_DEF_8"));
      tmpDmsDocument.setUserDef9(getResultSetString(rs, "USER_DEF_9"));
      tmpDmsDocument.setUserDef10(getResultSetString(rs, "USER_DEF_10"));
      tmpDmsDocument.setRecordStatus(getResultSetString(rs, "RECORD_STATUS"));
      tmpDmsDocument.setUpdateCount(getResultSetInteger(rs, "UPDATE_COUNT"));
      tmpDmsDocument.setCreatorID(getResultSetInteger(rs, "CREATOR_ID"));
      tmpDmsDocument.setCreateDate(getResultSetTimestamp(rs, "CREATE_DATE"));
      tmpDmsDocument.setUpdaterID(getResultSetInteger(rs, "UPDATER_ID"));
      tmpDmsDocument.setUpdateDate(getResultSetTimestamp(rs, "UPDATE_DATE"));
      tmpDmsDocument.setCreatorName(UserInfoFactory.getUserFullName(tmpDmsDocument.getCreatorID()));
      tmpDmsDocument.setUpdaterName(UserInfoFactory.getUserFullName(tmpDmsDocument.getUpdaterID()));
    } catch (SQLException sqle) {
      log.error(sqle, sqle);
      throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
    } catch (Exception e) {
      log.error(e, e);
      throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
    }
    
    return tmpDmsDocument;
  }
  
  public synchronized AbstractBaseObject getByExtRef(String extRef, String recordStatus) throws
  ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE, A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID,  A.EXT_REF , A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        //sqlStat.append("WHERE  A.ID = ? AND A.RECORD_STATUS = ? ");
        sqlStat.append("WHERE  A.EXT_REF = ?  ");
        if (!Utility.isEmpty(recordStatus)) {
          sqlStat.append("AND RECORD_STATUS=?  ");
        }
        sqlStat.append(" ORDER BY ID ASC  ");     
        
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, extRef);
        if (!Utility.isEmpty(recordStatus)) {
          this.setPrepareStatement(preStat, 2, recordStatus);
        }
        rs = preStat.executeQuery();
        if (rs.next()) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          return (tmpDmsDocument);
        } else {
          return null;
        }
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  } 
  /**
   * get the bind folder list by workflowRecordID
   * @param workflowRecordID
   * @return
   * @throws ApplicationException
   */
  public synchronized List getBindFolderListByWorkflowRecordID(Integer workflowRecordID) throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    List result = new ArrayList();
    Timestamp currTime = Utility.getCurrentTimestamp();
    Timestamp oneDayBeforeCurrTime = Utility.addDay(currTime, -1);
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT DISTINCT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE, A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF,A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A, MTM_WF_RECORD_OBJECT_LINK B ");
        sqlStat.append("WHERE  A.RECORD_STATUS = ? ");
        sqlStat.append("       AND B.OBJECT_TYPE = ? ");//"D"
        sqlStat.append("       AND A.ROOT_ID = B.OBJECT_ID ");
        sqlStat.append("       AND A.PARENT_ID = 0 "); 
        sqlStat.append("       AND A.DOCUMENT_TYPE = ? ");
        sqlStat.append("       AND ((A.EFFECTIVE_START_DATE IS NULL OR A.EFFECTIVE_START_DATE <= ?) ");
        sqlStat.append("       AND (A.EFFECTIVE_END_DATE IS NULL OR A.EFFECTIVE_END_DATE > ?)) ");
        sqlStat.append("       AND B.WORKFLOW_RECORD_ID = ? " );  
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, GlobalConstant.RECORD_STATUS_ACTIVE);
        this.setPrepareStatement(preStat, 2, GlobalConstant.OBJECT_TYPE_DOCUMENT);
        this.setPrepareStatement(preStat, 3, DmsDocument.FOLDER_TYPE);
        this.setPrepareStatement(preStat, 4, currTime);
        this.setPrepareStatement(preStat, 5, oneDayBeforeCurrTime);
        this.setPrepareStatement(preStat, 6, workflowRecordID);
        
        rs = preStat.executeQuery();
        while (rs.next()) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          result.add(tmpDmsDocument);
        }
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  public synchronized List getDocumentListByUdfIndexID(Integer udfIndexID) throws ApplicationException {
    return this.getDocumentListByUdfIndexIDCreateDate(udfIndexID,null);
  }
  
  public synchronized List getDocumentListByUdfIndexIDCreateDate(Integer udfIndexID,Timestamp createDate) throws ApplicationException {
    return this.getDocumentListByUdfIndexIDCreateDate(udfIndexID, createDate, true);
  }
  
  /**
   * Gets the list of the DmsDocument object(s) with the given document profile index ID.
   * 
   * @param udfDetailID the document profiel Index ID
   * @param createDate only the document created before createDate will be select
   * @param ignorePersonal the personal document will be ignore if true (EIP-1448 07/01/15 LEE ADD);
   * @return list of the DmsDocument object 
   * @throws ApplicationException
   * @see com.dcivision.dms.bean.DmsDocumentIndex
   */
  public synchronized List getDocumentListByUdfIndexIDCreateDate(Integer udfIndexID,Timestamp createDate, boolean ignorePersonal) throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    List result = new ArrayList();
    
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE, A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF, A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10,DD.USER_DEFINED_FIELD_ID ,A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A , DMS_DOCUMENT_INDEX DD , DMS_ROOT R ");
        sqlStat.append("WHERE A.ITEM_STATUS = 'A' AND  A.RECORD_STATUS = ? ");
        sqlStat.append("AND A.ID = DD.DOCUMENT_ID ");
        sqlStat.append("AND A.ROOT_ID = R.ID ");
        sqlStat.append("AND DD.USER_DEFINED_FIELD_ID = ? ");
        if (ignorePersonal) {
          sqlStat.append("AND R.ROOT_TYPE = ? ");
        }
        if (!Utility.isEmpty(createDate)){
          sqlStat.append("AND A.CREATE_DATE <  ?");
        }
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        int counter = 1;
        this.setPrepareStatement(preStat, counter++, GlobalConstant.RECORD_STATUS_ACTIVE);
        this.setPrepareStatement(preStat, counter++, udfIndexID);
        if (ignorePersonal) {
          this.setPrepareStatement(preStat, counter++, DmsRoot.PUBLIC_ROOT);
        }
        if (!Utility.isEmpty(createDate)){
          this.setPrepareStatement(preStat,counter++,createDate);
        }
        rs = preStat.executeQuery();
        while (rs.next()) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          result.add(tmpDmsDocument);
        }
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  public synchronized List getListByParentIDAndDocumentType(Integer parentID, Integer rootID, String documentType, String recordStatus) throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    List result = new ArrayList();
    Timestamp currTime = Utility.getCurrentTimestamp();
    Timestamp oneDayBeforeCurrTime = Utility.addDay(currTime, -1);
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE, A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF,A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        sqlStat.append("WHERE  A.RECORD_STATUS = ? ");
        
        sqlStat.append(" AND A.PARENT_ID = ?   ");
        if (rootID != null) {
          sqlStat.append("AND A.ROOT_ID = ? ");
        }
        
        if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
          sqlStat.append("      AND (((A.EFFECTIVE_START_DATE IS NULL OR A.EFFECTIVE_START_DATE <=?) ");
          sqlStat.append("      AND (A.EFFECTIVE_END_DATE IS NULL OR A.EFFECTIVE_END_DATE >?)) ");
          sqlStat.append("      OR A.OWNER_ID = ?) ");
        }
        
        sqlStat.append("AND A.DOCUMENT_TYPE = ? ");
        
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        sqlStat.append("ORDER BY A.DOCUMENT_TYPE ASC, A.DOCUMENT_NAME ASC ");
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        int i = 0;
        this.setPrepareStatement(preStat, ++i, recordStatus);
        
        this.setPrepareStatement(preStat, ++i, parentID);
        if (rootID != null) {
          this.setPrepareStatement(preStat, ++i, rootID);
        }
        
        if(!SystemParameterFactory.getSystemParameterBoolean(SystemParameterConstant.DMS_SHOW_EXPIRE_DOC)){
          this.setPrepareStatement(preStat, ++i, currTime);
          this.setPrepareStatement(preStat, ++i, oneDayBeforeCurrTime);
          this.setPrepareStatement(preStat, ++i, this.sessionContainer.getUserRecordID());
        }
        
        this.setPrepareStatement(preStat, ++i, documentType);
        rs = preStat.executeQuery();
        while (rs.next()) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          result.add(tmpDmsDocument);
        }
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  
  public synchronized List getAllExtRefList() throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    List result = new ArrayList();
    Timestamp currTime = Utility.getCurrentTimestamp();
    Timestamp oneDayBeforeCurrTime = Utility.addDay(currTime, -1);
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT distinct  A.EXT_REF ");
        sqlStat.append("FROM   DMS_DOCUMENT A ");
        sqlStat.append("WHERE  A.RECORD_STATUS = ? ");
        sqlStat.append("       AND (((A.EFFECTIVE_START_DATE IS NULL OR A.EFFECTIVE_START_DATE <= ?) ");
        sqlStat.append("       AND (A.EFFECTIVE_END_DATE IS NULL OR A.EFFECTIVE_END_DATE > ?)) ");
        sqlStat.append("       AND A.OWNER_ID = ?) ");
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, GlobalConstant.RECORD_STATUS_ACTIVE);
        this.setPrepareStatement(preStat, 2, currTime);
        this.setPrepareStatement(preStat, 3, oneDayBeforeCurrTime);
        this.setPrepareStatement(preStat, 4, this.sessionContainer.getUserRecordID());
        
        rs = preStat.executeQuery();
        while (rs.next()) {
          String extRef = getResultSetString(rs, "EXT_REF");
          result.add(extRef);
        }
        return (result);
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  } 
  /****************************************************
   * Author:barbin
   * create Date: 2006-4-17
   * @param documentType
   * @return
   * @throws ApplicationException
   */
  public synchronized DmsDocument getDocumentByDocType(String documentType) throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    DmsDocument tmpDmsDocument = new DmsDocument();
    
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE,A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF, A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM   DMS_DOCUMENT A,DMS_ROOT R ");
        sqlStat.append("WHERE  A.RECORD_STATUS = ? AND A.ROOT_ID = R.ID AND R.ROOT_TYPE = ? ");
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, GlobalConstant.RECORD_STATUS_ACTIVE);
        this.setPrepareStatement(preStat, 2, documentType);
        //format the sql for any 'LIKE' statement contained
        sqlStat = this.getFormattedSQL(sqlStat.toString());
        rs = preStat.executeQuery();
        
        if (rs.next()) {
          tmpDmsDocument = parseObjectFromResultSet(rs);
          return (tmpDmsDocument);
        } else {
          return (null);
        }
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle,
            sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
      }
    }
  }
  
  /**
   * ***************************************************************************
   */
  
  public synchronized AbstractBaseObject insertOnly(AbstractBaseObject obj) throws ApplicationException {
    return this.insert(obj);
  }
  
  public List getIDListByParentID(Integer documentParentId, String[] documentTypes, String[] recordStatus) throws ApplicationException {
    return this.getIDListByParentID(documentParentId, documentTypes, recordStatus, null, null, null);
  }
  
  public List getIDListByParentID(Integer documentParentId, String[] documentTypes, String[] recordStatus, String dateFrom, String dateTo, String[] indexIds) throws ApplicationException {
    List documentParentIds = new ArrayList();
    documentParentIds.add(documentParentId);
    return this.getIDListByParentIDList(documentParentIds, documentTypes, recordStatus, dateFrom, dateTo, indexIds);
  }
  
  public List getIDListByParentIDList(List documentParentIds, String[] documentTypes, String[] recordStatus) throws ApplicationException {
    return this.getIDListByParentIDList(documentParentIds, documentTypes, recordStatus, null, null, null);
  }
  
  public List getIDListByParentIDList(List documentParentIds, String[] documentTypes, String[] recordStatus, String dateFrom, String dateTo, String[] indexIds) throws ApplicationException {
    if (documentParentIds == null || documentParentIds.isEmpty()) {
      return null;
    }
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    try {
      StringBuffer sqlStat = new StringBuffer();
      sqlStat.append("SELECT A.ID ");
      sqlStat.append("FROM DMS_DOCUMENT A ");
      if (indexIds != null && indexIds.length > 0) {
        sqlStat.append("INNER JOIN DMS_DOCUMENT_DETAIL B ON A.ID=B.DOCUMENT_ID ");
      }
      sqlStat.append("WHERE A.PARENT_ID IN (");
      for (int i = 0; i < documentParentIds.size(); i++) {
        sqlStat.append(i == 0 ? "?" : ",?");
      }
      sqlStat.append(") ");
      if (documentTypes != null && documentTypes.length > 0) {
        sqlStat.append("AND A.DOCUMENT_TYPE IN (");
        for (int i = 0; i < documentTypes.length; i++) {
          sqlStat.append(i != 0 ? ",?" : "?");
        }
        sqlStat.append(") ");
      }
      if (recordStatus != null && recordStatus.length > 0) {
        sqlStat.append("AND A.RECORD_STATUS IN (");
        for (int i = 0; i < recordStatus.length; i++) {
          sqlStat.append(i != 0 ? ",?" : "?");
        }
        sqlStat.append(") ");
      }
      if (DataSourceFactory.getDatabaseType() == DataSourceFactory.DB_ORACLE) {
        if (!Utility.isEmpty(dateFrom)) {
          sqlStat.append("AND A.CREATE_DATE >= TO_DATE('" + dateFrom + "','" + "YYYY-MM-DD HH24:MI:SS" + "')  ");
        }
        if (!Utility.isEmpty(dateTo)) {
          sqlStat.append("AND A.CREATE_DATE < TO_DATE('" + TextUtility.dbDateAdder(dateTo, 1) + "','" + "YYYY-MM-DD HH24:MI:SS" + "')  ");
        }
      } else {
        if (!Utility.isEmpty(dateFrom)) {
          sqlStat.append("AND A.CREATE_DATE >= '" + dateFrom + "'  ");
        }
        if (!Utility.isEmpty(dateTo)) {
          sqlStat.append("AND A.CREATE_DATE < '" + TextUtility.dbDateAdder(dateTo, 1) + "'  ");
        }
      }
      if (indexIds != null && indexIds.length > 0) {
        sqlStat.append(" AND (");
        for (int i = 0; i < indexIds.length; i++) {
          sqlStat.append((i == (indexIds.length - 1)) ? "B.USER_DEFINED_FIELD_ID = ?" : "B.USER_DEFINED_FIELD_ID = ? OR ");
        }
        sqlStat.append(") ");
      }
      pstmt = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
      int counter = 1;
      for (int i = 0; i < documentParentIds.size(); i++) {
        this.setPrepareStatement(pstmt, counter++, (Integer) documentParentIds.get(i));
      }
      if (documentTypes != null && documentTypes.length > 0) {
        for (int i = 0; i < documentTypes.length; i++) {
          this.setPrepareStatement(pstmt, counter++, documentTypes[i]);
        }
      }
      if (recordStatus != null && recordStatus.length > 0) {
        for (int i = 0; i < recordStatus.length; i++) {
          this.setPrepareStatement(pstmt, counter++, recordStatus[i]);
        }
      }
      if (indexIds != null && indexIds.length > 0) {
        for (int j = 0; j < indexIds.length; j++) {
          this.setPrepareStatement(pstmt, counter++, indexIds[j]);
        }
      }
      rs = pstmt.executeQuery();
      
      List result = new ArrayList();
      while (rs.next()) {
        result.add(new Integer(rs.getString("ID")));
      }
      return result;
    } catch (SQLException sqle) {
      log.error(sqle, sqle);
      throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
    } catch (Exception e) {
      log.error(e, e);
      throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
    } finally {
      try { rs.close(); } catch (Exception ignore) {} finally { rs = null; }
      try { pstmt.close(); } catch (Exception ignore) {} finally { pstmt = null; }
    }
  }
  
  public synchronized List getListByIDList(List documentIds) throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    List result = new ArrayList();
    try {
      sqlStat.append("SELECT DISTINCT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE,A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF, A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
      sqlStat.append("FROM   DMS_DOCUMENT A ");
      sqlStat.append("WHERE A.ID IN (");
      for (int i = 0; i < documentIds.size(); i++) {
        sqlStat.append(i != 0 ? ",?" : "?");
      }
      sqlStat.append(") ");
      
      preStat = dbConn.prepareStatement(sqlStat.toString());
      
      int counter = 1;
      for (int i = 0; i < documentIds.size(); i++) {
        this.setPrepareStatement(preStat, counter++, (Integer) documentIds.get(i));
      }
      rs = preStat.executeQuery();
      while (rs.next()) {
        DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
        result.add(tmpDmsDocument);
      }
      return (result);
    } catch (ApplicationException appEx) {
      throw appEx;
    } catch (SQLException sqle) {
      log.error(sqle, sqle);
      throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
    } catch (Exception e) {
      log.error(e, e);
      throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
    } finally {
      try { rs.close(); } catch (Exception ignore) {} finally { rs = null; }
      try { preStat.close(); } catch (Exception ignore) {} finally { preStat = null; }
    }
  }
  
  public synchronized Map getMapByIDList(List documentIds) throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    Map result = new HashMap();
    try {
      sqlStat.append("SELECT DISTINCT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE,A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF, A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
      sqlStat.append("FROM   DMS_DOCUMENT A ");
      sqlStat.append("WHERE A.ID IN (");
      for (int i = 0; i < documentIds.size(); i++) {
        sqlStat.append(i != 0 ? ",?" : "?");
      }
      sqlStat.append(") ");
      
      preStat = dbConn.prepareStatement(sqlStat.toString());
      
      int counter = 1;
      for (int i = 0; i < documentIds.size(); i++) {
        this.setPrepareStatement(preStat, counter++, (Integer) documentIds.get(i));
      }
      rs = preStat.executeQuery();
      while (rs.next()) {
        DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
        result.put(tmpDmsDocument.getID(), tmpDmsDocument);
      }
      return (result);
    } catch (ApplicationException appEx) {
      throw appEx;
    } catch (SQLException sqle) {
      log.error(sqle, sqle);
      throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
    } catch (Exception e) {
      log.error(e, e);
      throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
    } finally {
      try { rs.close(); } catch (Exception ignore) {} finally { rs = null; }
      try { preStat.close(); } catch (Exception ignore) {} finally { preStat = null; }
    }
  }
  
  /**
   * 
   * @param documentParentIds
   * @param recordStatus
   * @param dateFrom
   * @param dateTo
   * @param indexIds
   * @return
   * @throws ApplicationException
   */
  
  public synchronized Map getPidToCidListMap(List documentParentIds, String[] recordStatus, String dateFrom, String dateTo, String[] indexIds) throws ApplicationException {
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    Map result = new HashMap();
    try {
      StringBuffer sqlStat = new StringBuffer();
      sqlStat.append("SELECT A.PARENT_ID, A.ID ");
      sqlStat.append("FROM DMS_DOCUMENT A ");
      if (indexIds != null && indexIds.length > 0) {
        sqlStat.append("INNER JOIN DMS_DOCUMENT_DETAIL B ON A.ID=B.DOCUMENT_ID ");
      }
      sqlStat.append("WHERE A.PARENT_ID IN (");
      for (int i = 0; i < documentParentIds.size(); i++) {
        sqlStat.append(i == 0 ? "?" : ",?");
      }
      sqlStat.append(") ");
      if (recordStatus != null && recordStatus.length > 0) {
        sqlStat.append("AND A.RECORD_STATUS IN (");
        for (int i = 0; i < recordStatus.length; i++) {
          sqlStat.append(i != 0 ? ",?" : "?");
        }
        sqlStat.append(") ");
      }
      if (DataSourceFactory.getDatabaseType() == DataSourceFactory.DB_ORACLE) {
        if (!Utility.isEmpty(dateFrom)) {
          sqlStat.append("AND A.CREATE_DATE >= TO_DATE('" + dateFrom + "','" + "YYYY-MM-DD HH24:MI:SS" + "')  ");
        }
        if (!Utility.isEmpty(dateTo)) {
          sqlStat.append("AND A.CREATE_DATE < TO_DATE('" + TextUtility.dbDateAdder(dateTo, 1) + "','" + "YYYY-MM-DD HH24:MI:SS" + "')  ");
        }
      } else {
        if (!Utility.isEmpty(dateFrom)) {
          sqlStat.append("AND A.CREATE_DATE >= '" + dateFrom + "'  ");
        }
        if (!Utility.isEmpty(dateTo)) {
          sqlStat.append("AND A.CREATE_DATE < '" + TextUtility.dbDateAdder(dateTo, 1) + "'  ");
        }
      }
      if (indexIds != null && indexIds.length > 0) {
        sqlStat.append(" AND (");
        for (int i = 0; i < indexIds.length; i++) {
          sqlStat.append((i == (indexIds.length - 1)) ? "B.USER_DEFINED_FIELD_ID = ?" : "B.USER_DEFINED_FIELD_ID = ? OR ");
        }
        sqlStat.append(") ");
      }
      sqlStat.append("ORDER BY A.PARENT_ID");
      pstmt = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
      int counter = 1;
      for (int i = 0; i < documentParentIds.size(); i++) {
        this.setPrepareStatement(pstmt, counter++, (Integer) documentParentIds.get(i));
      }
      if (recordStatus != null && recordStatus.length > 0) {
        for (int i = 0; i < recordStatus.length; i++) {
          this.setPrepareStatement(pstmt, counter++, recordStatus[i]);
        }
      }
      if (indexIds != null && indexIds.length > 0) {
        for (int j = 0; j < indexIds.length; j++) {
          this.setPrepareStatement(pstmt, counter++, indexIds[j]);
        }
      }
      
      rs = pstmt.executeQuery();
      Integer old_pid = null;
      List cidList = null;
      while (rs.next()) {
        Integer pid = this.getResultSetInteger(rs, "PARENT_ID");
        Integer id = this.getResultSetInteger(rs, "ID");
        if (!pid.equals(old_pid)) {
          if (old_pid != null) {
            result.put(old_pid, cidList);
          }
          old_pid = pid;
          cidList = new ArrayList();
        }
        cidList.add(id);
      }
      if (cidList != null && !cidList.isEmpty()) {
        result.put(old_pid, cidList);
      }
      return (result);
    } catch (ApplicationException appEx) {
      throw appEx;
    } catch (SQLException sqle) {
      log.error(sqle, sqle);
      throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
    } catch (Exception e) {
      log.error(e, e);
      throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
    } finally {
      try {rs.close();} catch (Exception ignore) {} finally {  rs = null;}
      try {pstmt.close();} catch (Exception ignore) {} finally {pstmt = null;}
    }
  }
  
  public synchronized Map getMapIdToFieldValueArray(
      List documentIds, 
      String[] fieldNames,
      String[] fieldTypes) throws ApplicationException {
    return this.getMapIdToFieldValueArray(documentIds, fieldNames, fieldTypes, null, null, null, null);
  }
  
  /**
   * Gets a map from database limited by specifiying:
   * <pre>
   * 1. documentIds - the document(s) id
   * 2. fieldNames - return field name
   * 3. fieldTypes - return field type
   * 4. recordStatus - record status of the return document(s)
   * 5. dateFrom - the document(s) create after dateFrom
   * 6. dateTo - the document(s) create before dateTo
   * 7. indexIds - the document(s) with specifid document profile
   * </pre>
   * Key is id, and value is an array which contains field value.
   * @param documentIds
   * @param fieldNames 
   * @param fieldTypes 
   * @param recordStatus the document record_status
   * @param dateFrom the document create date after this specified date
   * @param dateTo the document create date before this specified date
   * @param indexIds String array of User defined profile ID {@link com.dcivision.framework.bean.SysUserDefinedIndex} 
   * @return
   * @throws ApplicationException
   * <pre>
   * 
   *            ApplicationException with the following message codes will be thrown
   *            ErrorConstant.ErrorConstant.DB_GENERAL_ERROR - General caught SQLException
   *            ErrorConstant.DB_SELECT_ERROR - All kind of caught Exception
   *  
   * </pre>
   */
  public synchronized Map getMapIdToFieldValueArray(
      List documentIds, 
      String[] fieldNames,
      String[] fieldTypes,
      String[] recordStatus, 
      String dateFrom, 
      String dateTo, 
      String[] indexIds) throws ApplicationException {
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    Map result = new HashMap();
    try {
      StringBuffer sqlStat = new StringBuffer();
      sqlStat.append("SELECT A.ID ");
      for (int i=0; i<fieldNames.length; i++) {
        sqlStat.append(","+fieldNames[i]+" ");
      }
      sqlStat.append("FROM DMS_DOCUMENT A ");
      if (indexIds != null && indexIds.length>0) {
        sqlStat.append("INNER JOIN DMS_DOCUMENT_DETAIL B ON A.ID=B.DOCUMENT_ID ");
      }
      sqlStat.append("WHERE A.ID IN (");
      for (int i = 0; i < documentIds.size(); i++) {
        sqlStat.append(i == 0 ? "?" : ",?");
      }
      sqlStat.append(") ");
      if (recordStatus!=null && recordStatus.length>0) {
        sqlStat.append("AND A.RECORD_STATUS IN (");
        for (int i=0; i<recordStatus.length; i++) {
          sqlStat.append(i!=0?",?":"?");
        }
        sqlStat.append(") ");
      }
      if (DataSourceFactory.getDatabaseType() == DataSourceFactory.DB_ORACLE) {
        if (!Utility.isEmpty(dateFrom)) {
          sqlStat.append("AND A.CREATE_DATE >= TO_DATE('" + dateFrom + "','"+ "YYYY-MM-DD HH24:MI:SS" +"')  ");
        }
        if (!Utility.isEmpty(dateTo)) {
          sqlStat.append("AND A.CREATE_DATE < TO_DATE('" + TextUtility.dbDateAdder(dateTo, 1) + "','" + "YYYY-MM-DD HH24:MI:SS" +"')  ");
        }
      }else{
        if (!Utility.isEmpty(dateFrom)) {
          sqlStat.append("AND A.CREATE_DATE >= '" + dateFrom + "'  ");
        }
        if (!Utility.isEmpty(dateTo)) {
          sqlStat.append("AND A.CREATE_DATE < '" + TextUtility.dbDateAdder(dateTo, 1) + "'  ");
        }
      }
      if (indexIds != null && indexIds.length>0) {
        sqlStat.append(" AND (");
        for (int i = 0; i < indexIds.length; i++) {
          sqlStat.append((i==(indexIds.length-1)) ? "B.USER_DEFINED_FIELD_ID = ?" :"B.USER_DEFINED_FIELD_ID = ? OR ");
        }
        sqlStat.append(") ");
      }
      sqlStat.append("ORDER BY A.ID");
      pstmt = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
      int counter = 1;
      for (int i = 0; i < documentIds.size(); i++) {
        this.setPrepareStatement(pstmt, counter++, (Integer) documentIds.get(i));
      }
      if (recordStatus!=null && recordStatus.length>0) {
        for (int i=0; i<recordStatus.length; i++) {
          this.setPrepareStatement(pstmt, counter++, recordStatus[i]);
        }
      }
      if (indexIds != null && indexIds.length>0) {
        for (int j = 0; j < indexIds.length; j++) {
          this.setPrepareStatement(pstmt, counter++, indexIds[j]);
        }
      }
      rs = pstmt.executeQuery();
      while (rs.next()) {
        Integer id = this.getResultSetInteger(rs, 1);
        Object[] fieldValues = new Object[fieldNames.length];
        for (int i=0; i<fieldNames.length; i++) {
          if (fieldTypes[i].equals("String")) {
            fieldValues[i] = this.getResultSetString(rs, i+2);
          }else if (fieldTypes[i].equals("Integer")) {
            fieldValues[i] = this.getResultSetInteger(rs, i+2);
          }else if (fieldTypes[i].equals("Timestamp")) {
            fieldValues[i] = this.getResultSetTimestamp(rs, i+2);
          }else {
            throw new ApplicationException("getMapIdToFieldValueArray():Not support this field type:"+fieldTypes[i]);
          }
        }
        result.put(id, fieldValues);
      }
      return (result);
    } catch (ApplicationException appEx) {
      throw appEx;
    } catch (SQLException sqle) {
      log.error(sqle, sqle);
      throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
    } catch (Exception e) {
      log.error(e, e);
      throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
    } finally {
      try {
        rs.close();
      } catch (Exception ignore) {
      } finally {
        rs = null;
      }
      try {
        pstmt.close();
      } catch (Exception ignore) {
      } finally {
        pstmt = null;
      }
    }
  }
  
  
  
  public synchronized Map getMapIdToDVCFieldValueArrayList(
      List documentIds, 
      String[] fieldNames, 
      String[] fieldTypes, 
      String orderBy) throws ApplicationException {
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    Map result = new HashMap();
    try {
      StringBuffer sqlStat = new StringBuffer();
      sqlStat.append("SELECT D.ID ");
      for (int i=0; i<fieldNames.length; i++) {
        sqlStat.append(","+fieldNames[i]+" ");
      }
      sqlStat.append("FROM DMS_DOCUMENT D INNER JOIN DMS_VERSION V ON D.ID=V.DOCUMENT_ID ");
      sqlStat.append("     INNER JOIN DMS_CONTENT C ON V.CONTENT_ID=C.ID ");
      sqlStat.append("WHERE D.ID IN (");
      for (int i = 0; i < documentIds.size(); i++) {
        sqlStat.append(i == 0 ? "?" : ",?");
      }
      sqlStat.append(") ");
      if (orderBy!=null && !orderBy.equals("")) {
        sqlStat.append("ORDER BY "+orderBy);
      }else {
        sqlStat.append("ORDER BY D.ID");
      }
      pstmt = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
      int counter = 1;
      for (int i = 0; i < documentIds.size(); i++) {
        this.setPrepareStatement(pstmt, counter++, (Integer) documentIds.get(i));
      }
      rs = pstmt.executeQuery();
      Integer old_id = null;
      List fieldList = null;
      while (rs.next()) {
        Integer id = this.getResultSetInteger(rs, "ID");
        Object[] fieldValues = new Object[fieldNames.length];
        for (int i=0; i<fieldNames.length; i++) {
          if (fieldTypes[i].equals("String")) {
            fieldValues[i] = this.getResultSetString(rs, i+2);
          }else if (fieldTypes[i].equals("Integer")) {
            fieldValues[i] = this.getResultSetInteger(rs, i+2);
          }else if (fieldTypes[i].equals("Timestamp")) {
            fieldValues[i] = this.getResultSetTimestamp(rs, i+2);
          }else {
            throw new ApplicationException("getMapIdToFieldValueArray():Not support this field type:"+fieldTypes[i]);
          }
        }    
        if (!id.equals(old_id)) {
          if (old_id != null) {
            result.put(old_id, fieldList);
          }
          old_id = id;
          fieldList = new ArrayList();
        }
        fieldList.add(fieldValues);
      }
      if (fieldList != null && !fieldList.isEmpty()) {
        result.put(old_id, fieldList);
      }
      return (result);
    } catch (ApplicationException appEx) {
      throw appEx;
    } catch (SQLException sqle) {
      log.error(sqle, sqle);
      throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
    } catch (Exception e) {
      log.error(e, e);
      throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
    } finally {
      try {rs.close(); } catch (Exception ignore) { } finally { rs = null; }
      try { pstmt.close(); } catch (Exception ignore) { } finally { pstmt = null; }
    }
  }
  
  /**
   *  @deprecated This method is deprecated.
   */
  public synchronized List getFieldListById(
      String[] fieldNames, 
      String[] fieldTypes, 
      Integer id, 
      String[] itemStatus,
      boolean isItemStatusMatch,
      String[] recordStatus,
      boolean isRecordStatusMatch,
      String dateFrom, 
      String dateTo, 
      String[] indexIds,
      String orderBy) throws ApplicationException {
    return this.getFieldList(fieldNames, fieldTypes, id, false, itemStatus, isItemStatusMatch, recordStatus, isRecordStatusMatch, dateFrom, dateTo, indexIds, orderBy);
  }
  
  /**
   *  @deprecated This method is deprecated.
   */
  public synchronized List getFieldListByParentId(
      String[] fieldNames, 
      String[] fieldTypes, 
      Integer id, 
      String[] itemStatus,
      boolean isItemStatusMatch,
      String[] recordStatus,
      boolean isRecordStatusMatch,
      String dateFrom, 
      String dateTo, 
      String[] indexIds,
      String orderBy) throws ApplicationException {
    return this.getFieldList(fieldNames, fieldTypes, id, true, itemStatus, isItemStatusMatch, recordStatus, isRecordStatusMatch, dateFrom, dateTo, indexIds, orderBy);
  }
  
  /**
   * 
   * @param fieldNames
   * @param fieldTypes
   * @param id
   * @param isParentId
   * @param itemStatus
   * @param isItemStatusMatch
   * @param recordStatus
   * @param isRecordStatusMatch
   * @param dateFrom
   * @param dateTo
   * @param indexIds
   * @param orderBy
   * @return
   * @throws ApplicationException
   *  @deprecated This method is deprecated.
   */
  public synchronized List getFieldList(
      String[] fieldNames, 
      String[] fieldTypes, 
      Integer id, 
      boolean isParentId,
      String[] itemStatus,
      boolean isItemStatusMatch,
      String[] recordStatus,
      boolean isRecordStatusMatch,
      String dateFrom, 
      String dateTo, 
      String[] indexIds,
      String orderBy) throws ApplicationException {
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    try {
      StringBuffer sqlStat = new StringBuffer();
      sqlStat.append("SELECT ");
      for (int i=0; i<fieldNames.length; i++) {
        sqlStat.append(i == 0 ? fieldNames[i]+" " : ","+fieldNames[i]+" ");
      }
      sqlStat.append("FROM DMS_DOCUMENT D ");
      if (indexIds != null && indexIds.length > 0) {
        sqlStat.append("INNER JOIN DMS_DOCUMENT_DETAIL T ON D.ID=T.DOCUMENT_ID ");
      }
      sqlStat.append("WHERE "+(isParentId ? "D.PARENT_ID" : "D.ID")+"=? ");
      if (itemStatus!=null && itemStatus.length>0) {
        sqlStat.append("AND D.ITEM_STATUS "+(isItemStatusMatch ? "IN" : "NOT IN")+" (");
        for (int i = 0; i < itemStatus.length; i++) {
          sqlStat.append(i == 0 ? "?" : ",?");
        }
        sqlStat.append(") ");
      }
      if (recordStatus!=null && recordStatus.length>0) {
        sqlStat.append("AND D.RECORD_STATUS "+(isRecordStatusMatch ? "IN" : "NOT IN")+" (");
        for (int i = 0; i < recordStatus.length; i++) {
          sqlStat.append(i == 0 ? "?" : ",?");
        }
        sqlStat.append(") ");
      }
      if (DataSourceFactory.getDatabaseType() == DataSourceFactory.DB_ORACLE) {
        if (!Utility.isEmpty(dateFrom)) {
          sqlStat.append("AND D.CREATE_DATE >= TO_DATE('" + dateFrom + "','" + "YYYY-MM-DD HH24:MI:SS" + "')  ");
        }
        if (!Utility.isEmpty(dateTo)) {
          sqlStat.append("AND D.CREATE_DATE < TO_DATE('" + TextUtility.dbDateAdder(dateTo, 1) + "','" + "YYYY-MM-DD HH24:MI:SS" + "')  ");
        }
      } else {
        if (!Utility.isEmpty(dateFrom)) {
          sqlStat.append("AND D.CREATE_DATE >= '" + dateFrom + "'  ");
        }
        if (!Utility.isEmpty(dateTo)) {
          sqlStat.append("AND D.CREATE_DATE < '" + TextUtility.dbDateAdder(dateTo, 1) + "'  ");
        }
      }
      if (indexIds != null && indexIds.length > 0) {
        sqlStat.append(" AND (");
        for (int i = 0; i < indexIds.length; i++) {
          sqlStat.append((i == (indexIds.length - 1)) ? "T.USER_DEFINED_FIELD_ID = ?" : "T.USER_DEFINED_FIELD_ID = ? OR ");
        }
        sqlStat.append(") ");
      }
      if (orderBy!=null && !orderBy.equals("")) {
        sqlStat.append("ORDER BY "+orderBy);
      }else {
        sqlStat.append("ORDER BY D.DOCUMENT_TYPE, D.ID ");
      }
      pstmt = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
      int counter = 1;
      this.setPrepareStatement(pstmt, counter++, id);
      if (itemStatus!=null && itemStatus.length>0) {
        for (int i = 0; i < itemStatus.length; i++) {
          this.setPrepareStatement(pstmt, counter++, itemStatus[i]);
        }
      }
      if (recordStatus!=null && recordStatus.length>0) {
        for (int i = 0; i < recordStatus.length; i++) {
          this.setPrepareStatement(pstmt, counter++, recordStatus[i]);
        }
      }
      if (indexIds != null && indexIds.length > 0) {
        for (int j = 0; j < indexIds.length; j++) {
          this.setPrepareStatement(pstmt, counter++, indexIds[j]);
        }
      }
      rs = pstmt.executeQuery();
      List fieldList = new ArrayList();
      while (rs.next()) {
        Object[] fieldValues = new Object[fieldNames.length];
        for (int i=0; i<fieldNames.length; i++) {
          if (fieldTypes[i].equals("String")) {
            fieldValues[i] = this.getResultSetString(rs, i+1);
          }else if (fieldTypes[i].equals("Integer")) {
            fieldValues[i] = this.getResultSetInteger(rs, i+1);
          }else if (fieldTypes[i].equals("Timestamp")) {
            fieldValues[i] = this.getResultSetTimestamp(rs, i+1);
          }else {
            throw new ApplicationException("getFieldList():Not support this field type:"+fieldTypes[i]);
          }
        }
        fieldList.add(fieldValues);
      }
      return (fieldList);
    } catch (ApplicationException appEx) {
      throw appEx;
    } catch (SQLException sqle) {
      log.error(sqle, sqle);
      throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
    } catch (Exception e) {
      log.error(e, e);
      throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
    } finally {
      try {rs.close();} catch (Exception ignore) {} finally {  rs = null;}
      try {pstmt.close();} catch (Exception ignore) {} finally {pstmt = null;}
    }
  }
  
  public synchronized List getDVCFieldListByDocumentID(
      String[] fieldNames, 
      String[] fieldTypes, 
      Integer id, 
      String[] itemStatus,
      boolean isItemStatusMatch,
      String[] recordStatus,
      boolean isRecordStatusMatch,
      String orderBy) throws ApplicationException {
    return this.getDVCFieldList(fieldNames, fieldTypes, id, false, itemStatus, isItemStatusMatch, recordStatus, isRecordStatusMatch, orderBy);
  }
  
  public synchronized List getDVCFieldListByDocumentParentID(
      String[] fieldNames, 
      String[] fieldTypes, 
      Integer parentId, 
      String[] itemStatus,
      boolean isItemStatusMatch,
      String[] recordStatus,
      boolean isRecordStatusMatch,
      String orderBy) throws ApplicationException {
    return this.getDVCFieldList(fieldNames, fieldTypes, parentId, true, itemStatus, isItemStatusMatch, recordStatus, isRecordStatusMatch, orderBy);
  }
  
  public synchronized List getDVCFieldList(
      String[] fieldNames, 
      String[] fieldTypes, 
      Integer id, 
      boolean isParentId,
      String[] itemStatus,
      boolean isItemStatusMatch,
      String[] recordStatus,
      boolean isRecordStatusMatch,
      String orderBy) throws ApplicationException {
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    try {
      StringBuffer sqlStat = new StringBuffer();
      sqlStat.append("SELECT ");
      for (int i=0; i<fieldNames.length; i++) {
        sqlStat.append(i == 0 ? fieldNames[i]+" " : ","+fieldNames[i]+" ");
      }
      sqlStat.append("FROM DMS_DOCUMENT D INNER JOIN DMS_VERSION V ON D.ID=V.DOCUMENT_ID ");
      sqlStat.append("     INNER JOIN DMS_CONTENT C ON V.CONTENT_ID=C.ID ");
      sqlStat.append("WHERE "+(isParentId ? "D.PARENT_ID" : "D.ID")+"=? ");
      if (itemStatus!=null && itemStatus.length>0) {
        sqlStat.append("AND D.ITEM_STATUS "+(isItemStatusMatch ? "IN" : "NOT IN")+" (");
        for (int i = 0; i < itemStatus.length; i++) {
          sqlStat.append(i == 0 ? "?" : ",?");
        }
        sqlStat.append(") ");
      }
      if (recordStatus!=null && recordStatus.length>0) {
        sqlStat.append("AND D.RECORD_STATUS "+(isRecordStatusMatch ? "IN" : "NOT IN")+" (");
        for (int i = 0; i < recordStatus.length; i++) {
          sqlStat.append(i == 0 ? "?" : ",?");
        }
        sqlStat.append(") ");
      }
      if (orderBy!=null && !orderBy.equals("")) {
        sqlStat.append("ORDER BY "+orderBy);
      }else {
        sqlStat.append("ORDER BY D.DOCUMENT_TYPE ASC, D.ID ASC, V.VERSION_NUMBER DESC");
      }
      pstmt = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
      int counter = 1;
      this.setPrepareStatement(pstmt, counter++, id);
      if (itemStatus!=null && itemStatus.length>0) {
        for (int i = 0; i < itemStatus.length; i++) {
          this.setPrepareStatement(pstmt, counter++, itemStatus[i]);
        }
      }
      if (recordStatus!=null && recordStatus.length>0) {
        for (int i = 0; i < recordStatus.length; i++) {
          this.setPrepareStatement(pstmt, counter++, recordStatus[i]);
        }
      }
      rs = pstmt.executeQuery();
      
      List fieldList = new ArrayList();
      while (rs.next()) {
        Object[] fieldValues = new Object[fieldNames.length];
        for (int i=0; i<fieldNames.length; i++) {
          if (fieldTypes[i].equals("String")) {
            fieldValues[i] = this.getResultSetString(rs, i+1);
          }else if (fieldTypes[i].equals("Integer")) {
            fieldValues[i] = this.getResultSetInteger(rs, i+1);
          }else if (fieldTypes[i].equals("Timestamp")) {
            fieldValues[i] = this.getResultSetTimestamp(rs, i+1);
          }else {
            throw new ApplicationException("getDVCFieldList():Not support this field type:"+fieldTypes[i]);
          }
        }
        fieldList.add(fieldValues);
      }
      return (fieldList);
    } catch (ApplicationException appEx) {
      throw appEx;
    } catch (SQLException sqle) {
      log.error(sqle, sqle);
      throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
    } catch (Exception e) {
      log.error(e, e);
      throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
    } finally {
      try {
        rs.close();
      } catch (Exception ignore) {
      } finally {
        rs = null;
      }
      try {
        pstmt.close();
      } catch (Exception ignore) {
      } finally {
        pstmt = null;
      }
    }
  }
  
  /**
   * Update(soft delete) DMS_DOCUMENT record_status by gived doucments' id.
   * lee.lv add in 06/06/19
   * @param documentIds
   * @param recordStatus
   * @throws ApplicationException
   */
//public synchronized void updateRecordStatusByIDList(List documentIds, String recordStatus) throws  ApplicationException {
//joan.xiong update code for bug EIP-144 by 2006/10/11
  public synchronized void updateRecordStatusByIDList(List documentIds, String recordStatus,Integer updaterID) throws  ApplicationException {
    PreparedStatement preStat = null;
    StringBuffer sqlStat = new StringBuffer();
    try {
      sqlStat.append("UPDATE DMS_DOCUMENT ");
      sqlStat.append("SET RECORD_STATUS=? ");
      /*
       * joan.xiong add code for bug EIP-144 by 2006/10/11
       */
      if(!Utility.isEmpty(updaterID)){
        sqlStat.append(",UPDATE_COUNT=UPDATE_COUNT+1 ");
        sqlStat.append(",UPDATER_ID=? ");
        sqlStat.append(",UPDATE_DATE=? ");
      }
      /*
       * joan.xiong add code end
       */
      sqlStat.append("WHERE ID IN (");
      for (int i=0; i<documentIds.size(); i++) {
        sqlStat.append(i!=0?",?":"?");
      }
      sqlStat.append(")");
      
      preStat = dbConn.prepareStatement(sqlStat.toString());
      
      int counter = 1;
      this.setPrepareStatement(preStat, counter++, recordStatus);
      /*
       * joan.xiong add code for bug EIP-144 by 2006/10/11
       */
      if(!Utility.isEmpty(updaterID)){
        this.setPrepareStatement(preStat, counter++, updaterID);
        this.setPrepareStatement(preStat, counter++, Utility.getCurrentTimestamp());
      }
      /*
       * joan.xiong add code end
       */
      for (int i=0; i<documentIds.size(); i++) {
        this.setPrepareStatement(preStat, counter++, (Integer)documentIds.get(i));
      }
      preStat.executeUpdate();
    } catch (SQLException sqle) {
      log.error(sqle, sqle);
      throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
    } catch (Exception e) {
      log.error(e, e);
      throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
    } finally {
      try { preStat.close(); } catch (Exception ignore) {} finally { preStat = null; }
    }
  }
  
  /**
   * Upate item_status by gived documents' id.
   * lee.lv add in 06/06/19
   * @param documentIds
   * @param recordStatus
   * @throws ApplicationException
   */
  public synchronized void updateItemStatusByIDList(List documentIds, String itemStatus) throws  ApplicationException {
    PreparedStatement preStat = null;
    StringBuffer sqlStat = new StringBuffer();
    try {
      sqlStat.append("UPDATE DMS_DOCUMENT ");
      sqlStat.append("SET ITEM_STATUS=?, UPDATER_ID=?, UPDATE_DATE=?, UPDATE_COUNT=UPDATE_COUNT+1 ");
      sqlStat.append("WHERE ID IN (");
      for (int i=0; i<documentIds.size(); i++) {
        sqlStat.append(i!=0?",?":"?");
      }
      sqlStat.append(")");
      
      preStat = dbConn.prepareStatement(sqlStat.toString());
      Integer updaterID = sessionContainer.getUserRecordID()!=null ? sessionContainer.getUserRecordID() : new Integer("0");
      int counter = 1;
      this.setPrepareStatement(preStat, counter++, itemStatus);
      this.setPrepareStatement(preStat, counter++, updaterID);
      this.setPrepareStatement(preStat, counter++, Utility.getCurrentTimestamp());
      for (int i=0; i<documentIds.size(); i++) {
        this.setPrepareStatement(preStat, counter++, (Integer)documentIds.get(i));
      }
      preStat.executeUpdate();
    } catch (SQLException sqle) {
      log.error(sqle, sqle);
      throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
    } catch (Exception e) {
      log.error(e, e);
      throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
    } finally {
      try { preStat.close(); } catch (Exception ignore) {} finally { preStat = null; }
    }
  }
  
  public synchronized List getAlertListByIDList(
      List documentIds,
      String actionType,
      String recordStatus) throws ApplicationException {
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    List resultList = new ArrayList();
    synchronized(dbConn) {
      try {
        sqlStat.append("SELECT DISTINCT A.ID, A.DOCUMENT_NAME, A.DOCUMENT_TYPE, A.PARENT_ID, A.ROOT_ID, A.PRIORITY, A.CREATE_TYPE, A.EFFECTIVE_START_DATE, A.EFFECTIVE_END_DATE,A.REMINDER_AMOUNT, A.REMINDER_TYPE, A.NOTIFICATION_WAY,A.OWNER_ID, A.REFERENCE_NO, A.DESCRIPTION, A.ITEM_SIZE, A.ITEM_STATUS, A.CHECKOUT_ID, A.ALERT_EDIT_ID, A.ALERT_INVITE_ID, A.EXT_REF, A.USER_DEF_1, A.USER_DEF_2, A.USER_DEF_3, A.USER_DEF_4, A.USER_DEF_5, A.USER_DEF_6, A.USER_DEF_7, A.USER_DEF_8, A.USER_DEF_9, A.USER_DEF_10, A.RECORD_STATUS, A.UPDATE_COUNT, A.CREATOR_ID, A.CREATE_DATE, A.UPDATER_ID, A.UPDATE_DATE ");
        sqlStat.append("FROM DMS_DOCUMENT A INNER JOIN UPDATE_ALERT B ON A.ID=B.OBJECT_ID INNER JOIN UPDATE_ALERT_TYPE C ON B.ID=C.UPDATE_ALERT_ID ");
        sqlStat.append("WHERE B.OBJECT_TYPE='"+UpdateAlert.DOCUMENT_TYPE+"' ");
        if (recordStatus!=null){
          sqlStat.append("    AND B.RECORD_STATUS=? ");
        }
        if (actionType!=null) {
          sqlStat.append("    AND C.ACTION_TYPE=? ");
        }
        sqlStat.append("      AND A.ID IN (");
        for (int i=0; i<documentIds.size(); i++) {
          sqlStat.append(i!=0?",?":"?");
        }
        sqlStat.append(")");
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        int counter = 1;
        if (recordStatus!=null) {
          this.setPrepareStatement(preStat, counter++, recordStatus);
        }
        if (actionType!=null) {
          this.setPrepareStatement(preStat, counter++, actionType);
        }
        for (int i=0; i<documentIds.size(); i++) {
          this.setPrepareStatement(preStat, counter++, (Integer)documentIds.get(i));
        }
        rs = preStat.executeQuery();
        while (rs.next()) {
          DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
          resultList.add(tmpDmsDocument);
        }
        return resultList;
      } catch (ApplicationException appEx) {
        throw appEx;
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
        throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
      } catch (Exception e) {
        log.error(e, e);
        throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
      } finally {
        try { rs.close(); } catch (Exception ignore) {} finally { rs = null; }
        try { preStat.close(); } catch (Exception ignore) {} finally { preStat = null; }
      }
    }
    
  }
  
  /*barbin 2006-8-15 paraScan
   * get all checkout document for user
   * @param recordStatus;
   * @param creatorID;
   */
  public synchronized List getListForCheckout(String recordStatus,String creatorID)throws Exception{
    List checkoutList = new ArrayList();
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    try{
      sqlStat.append("SELECT * FROM DMS_DOCUMENT A, DMS_CHECKOUT_HISTORY B ");
      sqlStat.append("WHERE A.CHECKOUT_ID = B.ID AND A.RECORD_STATUS = ? AND A.CHECKOUT_ID IS NOT NULL AND B.CREATOR_ID = ? ");
      sqlStat.append("ORDER BY A.DOCUMENT_TYPE ASC");
      preStat = dbConn.prepareStatement(sqlStat.toString());
      this.setPrepareStatement(preStat,1,recordStatus);
      this.setPrepareStatement(preStat,2,creatorID);
      rs = preStat.executeQuery();
      while(rs.next()){
        DmsDocument tmpDmsDocument = parseObjectFromResultSet(rs);
        checkoutList.add(tmpDmsDocument);
      }
      return checkoutList;
    }catch(Exception e){
      throw e;
    }finally{
      try { rs.close(); } catch (Exception ignore) {} finally { rs = null; }
      try { preStat.close(); } catch (Exception ignore) {} finally { preStat = null; }
    }
  }
  
  /* Jicle.Wang 5816 2006/08/10 Start */
  public String getPostfixByID(Integer id){
    PreparedStatement preStat = null;
    ResultSet rs = null;
    StringBuffer sqlStat = new StringBuffer();
    String result = "";
    synchronized (dbConn) {
      try {
        sqlStat.append("SELECT DC.EXT ")
        .append("FROM DMS_DOCUMENT DD, DMS_CONTENT DC, DMS_VERSION DV ")
        .append("WHERE DV.RECORD_STATUS = ? ")
        .append("AND DD.RECORD_STATUS = ? ")
        .append("AND DC.RECORD_STATUS = ? ")
        .append("AND DD.ID = DV.DOCUMENT_ID ")
        .append("AND DV.CONTENT_ID = DC.ID  ")
        .append("AND DD.ID=? ")
        .append("ORDER BY DC.ID DESC ");
        preStat = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        this.setPrepareStatement(preStat, 1, GlobalConstant.RECORD_STATUS_ACTIVE);
        this.setPrepareStatement(preStat, 2, GlobalConstant.RECORD_STATUS_ACTIVE);
        this.setPrepareStatement(preStat, 3, GlobalConstant.RECORD_STATUS_ACTIVE);
        this.setPrepareStatement(preStat, 4, id);
        rs = preStat.executeQuery();
        if (rs.next()) {
          result = getResultSetString(rs, "EXT");
        } 
      } catch (SQLException sqle) {
        log.error(sqle, sqle);
      } catch (Exception e) {
        log.error(e, e);
      } finally {
        try {
          rs.close();
        } catch (Exception ignore) {} finally {
          rs = null;
        }
        try {
          preStat.close();
        } catch (Exception ignore) {} finally {
          preStat = null;
        }
        
      }
    }
    return result;
  }
  /* Jicle.Wang 5816 2006/08/10 End   */
  
  /**
   * return a map object, key is gived parent id, value is a list which contains all children ids.
   * if one of the gived parent id has not children, then map will not contains the id information whose not children.
   * @param documentParentIds
   * @param recordStatus
   * @param dateFrom
   * @param dateTo
   * @param indexIds
   * @return
   * @throws ApplicationException
   */
  public synchronized Map getPIDtoIDMapByIDList(
      List documentParentIds, 
      String[] recordStatus, 
      String dateFrom, 
      String dateTo, 
      String[] indexIds) throws ApplicationException {
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    Map result = new HashMap();
    try {
      StringBuffer sqlStat = new StringBuffer();
      sqlStat.append("SELECT A.PARENT_ID, A.ID ");
      sqlStat.append("FROM DMS_DOCUMENT A ");
      if (indexIds != null && indexIds.length>0) {
        sqlStat.append("INNER JOIN DMS_DOCUMENT_DETAIL B ON A.ID=B.DOCUMENT_ID ");
      }
      sqlStat.append("WHERE A.PARENT_ID IN (");
      for (int i=0; i<documentParentIds.size(); i++) {
        sqlStat.append(i==0 ? "?" : ",?");
      }
      sqlStat.append(") ");
      if (recordStatus!=null && recordStatus.length>0) {
        sqlStat.append("AND A.RECORD_STATUS IN (");
        for (int i=0; i<recordStatus.length; i++) {
          sqlStat.append(i!=0?",?":"?");
        }
        sqlStat.append(") ");
      }
      if (DataSourceFactory.getDatabaseType() == DataSourceFactory.DB_ORACLE) {
        if (!Utility.isEmpty(dateFrom)) {
          sqlStat.append("AND A.CREATE_DATE >= TO_DATE('" + dateFrom + "','"+ "YYYY-MM-DD HH24:MI:SS" +"')  ");
        }
        if (!Utility.isEmpty(dateTo)) {
          sqlStat.append("AND A.CREATE_DATE < TO_DATE('" + TextUtility.dbDateAdder(dateTo, 1) + "','" + "YYYY-MM-DD HH24:MI:SS" +"')  ");
        }
      }else{
        if (!Utility.isEmpty(dateFrom)) {
          sqlStat.append("AND A.CREATE_DATE >= '" + dateFrom + "'  ");
        }
        if (!Utility.isEmpty(dateTo)) {
          sqlStat.append("AND A.CREATE_DATE < '" + TextUtility.dbDateAdder(dateTo, 1) + "'  ");
        }
      }
      if (indexIds != null && indexIds.length>0) {
        sqlStat.append(" AND (");
        for (int i = 0; i < indexIds.length; i++) {
          sqlStat.append((i==(indexIds.length-1)) ? "B.USER_DEFINED_FIELD_ID = ?" :"B.USER_DEFINED_FIELD_ID = ? OR ");
        }
        sqlStat.append(") ");
      }
      sqlStat.append("ORDER BY A.PARENT_ID");
      pstmt = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
      int counter = 1;
      for (int i=0; i<documentParentIds.size(); i++) {
        this.setPrepareStatement(pstmt, counter++, (Integer)documentParentIds.get(i));  
      }
      if (recordStatus!=null && recordStatus.length>0) {
        for (int i=0; i<recordStatus.length; i++) {
          this.setPrepareStatement(pstmt, counter++, recordStatus[i]);
        }
      }
      if (indexIds != null && indexIds.length>0) {
        for (int j = 0; j < indexIds.length; j++) {
          this.setPrepareStatement(pstmt, counter++, indexIds[j]);
        }
      }
      
      rs = pstmt.executeQuery();
      Integer old_pid = null;
      List cidList = null;
      while (rs.next()) {
        Integer pid = this.getResultSetInteger(rs, "PARENT_ID");
        Integer id = this.getResultSetInteger(rs, "ID");
        if (!pid.equals(old_pid)) {
          if (old_pid!=null) {
            result.put(old_pid, cidList);
          }
          old_pid = pid;
          cidList = new ArrayList();
        }
        cidList.add(id);
      }
      if (cidList!=null && !cidList.isEmpty()) {
        result.put(old_pid, cidList);
      }
      return (result);
    } catch (ApplicationException appEx) {
      throw appEx;
    } catch (SQLException sqle) {
      log.error(sqle, sqle);
      throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
    } catch (Exception e) {
      log.error(e, e);
      throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
    } finally {
      try { rs.close(); } catch (Exception ignore) {} finally { rs = null; }
      try { pstmt.close(); } catch (Exception ignore) {} finally { pstmt = null; }
    }
  }
  
  /*************************
   * this method according to objectIds get its all sub documents 
   * @author barbin
   * @param objectID
   * @param rootID
   * @return list
   * @throws ApplicationException
   */
  public List getAllsubFolderDocIDsByObjectID(Integer objectID, Integer rootID)throws ApplicationException{
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    List allList = new ArrayList();
    try {
      StringBuffer sqlStat = new StringBuffer();
      sqlStat.append("SELECT A.ID ");
      sqlStat.append("FROM DMS_DOCUMENT A ");
      sqlStat.append("WHERE A.ROOT_ID = ? AND A.PARENT_ID = ?");
      pstmt = dbConn.prepareStatement(sqlStat.toString(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
      this.setPrepareStatement(pstmt,1,rootID);
      this.setPrepareStatement(pstmt,2,objectID);
     
      rs = pstmt.executeQuery();
      while (rs.next()) {
        Integer id = this.getResultSetInteger(rs, "ID");
        allList.add(id);
      }
      return (allList);
    } catch (ApplicationException appEx) {
      throw appEx;
    } catch (SQLException sqle) {
      log.error(sqle, sqle);
      throw new ApplicationException(ErrorConstant.DB_GENERAL_ERROR, sqle, sqle.toString());
    } catch (Exception e) {
      log.error(e, e);
      throw new ApplicationException(ErrorConstant.DB_SELECT_ERROR, e);
    } finally {
      try { rs.close(); } catch (Exception ignore) {} finally { rs = null; }
      try { pstmt.close(); } catch (Exception ignore) {} finally { pstmt = null; }
    }
  }
}
